[
  {
    "path": ".clang-format",
    "content": "---\nAccessModifierOffset: -1\nAlignAfterOpenBracket: AlwaysBreak\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlinesLeft: true\nAlignOperands:   false\nAlignTrailingComments: false\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: Empty\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: true\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: false\nBinPackParameters: false\nBraceWrapping:\n  AfterClass:      false\n  AfterControlStatement: false\n  AfterEnum:       false\n  AfterFunction:   false\n  AfterNamespace:  false\n  AfterObjCDeclaration: false\n  AfterStruct:     false\n  AfterUnion:      false\n  BeforeCatch:     false\n  BeforeElse:      false\n  IndentBraces:    false\nBreakBeforeBinaryOperators: None\nBreakBeforeBraces: Attach\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: false\nBreakAfterJavaFieldAnnotations: false\nBreakStringLiterals: false\nColumnLimit:     100\nCommentPragmas:  '^ IWYU pragma:'\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nDisableFormat:   false\nForEachMacros:   [ FOR_EACH_RANGE, FOR_EACH, ]\nIncludeCategories:\n  - Regex:           '^<.*\\.h(pp)?>'\n    Priority:        1\n  - Regex:           '^<.*'\n    Priority:        2\n  - Regex:           '.*'\n    Priority:        3\nIndentCaseLabels: true\nIndentWidth:     2\nIndentWrappedFunctionNames: false\nKeepEmptyLinesAtTheStartOfBlocks: false\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nObjCBlockIndentWidth: 2\nObjCSpaceAfterProperty: false\nObjCSpaceBeforeProtocolList: false\nPenaltyBreakBeforeFirstCallParameter: 1\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 200\nPointerAlignment: Left\nRawStringFormats:\n  - Language:        TextProto\n    Delimiters:\n      - pb\nReflowComments:  true\nSortIncludes:    true\nSpaceAfterCStyleCast: false\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeParens: ControlStatements\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 1\nSpacesInAngles:  false\nSpacesInContainerLiterals: true\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard:        Cpp11\nTabWidth:        4\nUseTab:          Never\n...\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: File a bug report\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"triage\"]\nassignees:\n  - graphicsMan\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: input\n    id: contact\n    attributes:\n      label: Contact Details\n      description: How can we get in touch with you if we need more info?\n      placeholder: ex. email@example.com\n    validations:\n      required: false\n  - type: textarea\n    id: what-happened\n    attributes:\n      label: What happened?\n      description: Also tell us, what did you expect to happen?\n      placeholder: Tell us what you see!\n      value: \"A bug happened!\"\n    validations:\n      required: true\n  - type: dropdown\n    id: version\n    attributes:\n      label: Version\n      description: What version of our software are you running?\n      options:\n        - 1.0 (Default)\n        - latest (Edge)\n    validations:\n      required: true\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com)\n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: File a feature request\ntitle: \"[Feature Request]: \"\nlabels: [\"feature\", \"request\"]\nassignees:\n  - graphicsMan\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this feature request!\n  - type: input\n    id: contact\n    attributes:\n      label: Contact Details\n      description: How can we get in touch with you if we need more info?\n      placeholder: ex. email@example.com\n    validations:\n      required: false\n  - type: textarea\n    id: whats-wanted\n    attributes:\n      label: What is the desired feature?\n      description: Give some details\n      value: \"Details here\"\n    validations:\n      required: true\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com)\n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "# PR Details\n\n<!--- Provide a general summary of your changes in the Title above -->\n\n## Description\n\n<!--- Describe your changes in detail -->\n\n## Related Issue\n\n<!--- Please link to the issue here: -->\n\n## Motivation and Context\n\n<!--- Why is this change required? What problem does it solve? -->\n\n## Test Plan\n\n<!--- Please describe in detail how you tested your changes. -->\n<!--- Include details of your testing environment, and the tests you ran to -->\n<!--- see how your change affects other areas of the code, etc. -->\n\n## Types of changes\n\n<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->\n\n- [ ] Docs change\n- [ ] Refactoring\n- [ ] Dependency upgrade\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to change)\n\n## Checklist\n\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n\n- [ ] My code follows the code style of this project.\n- [ ] I have run clang-format.\n- [ ] My change requires a change to the documentation.\n- [ ] I have updated the documentation accordingly.\n- [ ] I have read the **CONTRIBUTING** document.\n- [ ] I have added tests to cover my changes.\n- [ ] All new and existing tests passed, including in ASAN and TSAN modes (if available on your platform).\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build and test\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\npermissions:\n  contents: read\n\nenv:\n  CTEST_OUTPUT_ON_FAILURE: 1\n\njobs:\n  #############################################################################\n  # Core platform builds - strategic sampling of OS/compiler/standard/library\n  #############################################################################\n  build-matrix:\n    name: ${{ matrix.name }}\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          # Linux - GCC baseline\n          - name: Linux GCC C++14\n            os: ubuntu-latest\n            cmake_args: -DCMAKE_CXX_STANDARD=14\n          # Linux - Clang with C++20 concepts\n          - name: Linux Clang C++20\n            os: ubuntu-latest\n            cc: clang\n            cxx: clang++\n            cmake_args: -DCMAKE_CXX_STANDARD=20\n          # macOS - C++20 with static library\n          - name: macOS C++20 static\n            os: macos-latest\n            cmake_args: -DCMAKE_CXX_STANDARD=20 -DDISPENSO_SHARED_LIB=OFF\n          # Windows - MSVC baseline\n          - name: Windows MSVC C++14\n            os: windows-latest\n            cmake_args: -DCMAKE_CXX_STANDARD=14\n          # Windows - MSVC C++20 with static library\n          - name: Windows MSVC C++20 static\n            os: windows-latest\n            cmake_args: -DCMAKE_CXX_STANDARD=20 -DDISPENSO_SHARED_LIB=OFF\n    steps:\n      - uses: actions/checkout@v4\n      - name: Configure\n        run: |\n          mkdir build && cd build\n          cmake .. -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}\n        env:\n          CC: ${{ matrix.cc }}\n          CXX: ${{ matrix.cxx }}\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4 --config Release\n      - name: Test\n        working-directory: ./build\n        run: ctest -LE flaky --build-config Release\n\n  #############################################################################\n  # Architecture-specific builds\n  #############################################################################\n  build-linux-x86:\n    name: Linux x86 (32-bit)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install 32-bit support\n        run: sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib\n      - name: Configure\n        run: |\n          mkdir build && cd build\n          cmake .. -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release \\\n            -DCMAKE_CXX_FLAGS=\"-m32\" -DCMAKE_C_FLAGS=\"-m32\"\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4\n      - name: Test\n        working-directory: ./build\n        run: ctest -LE flaky\n\n  build-macos-gcc:\n    name: macOS GCC C++14 (ARM64)\n    runs-on: macos-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up GCC\n        run: |\n          brew list gcc || brew install gcc\n          GCC_PREFIX=$(brew --prefix gcc)\n          GCC_VER=$(ls \"$GCC_PREFIX/bin\"/gcc-* | grep -oE '[0-9]+$' | sort -n | tail -1)\n          echo \"CC=$GCC_PREFIX/bin/gcc-$GCC_VER\" >> $GITHUB_ENV\n          echo \"CXX=$GCC_PREFIX/bin/g++-$GCC_VER\" >> $GITHUB_ENV\n      - name: Configure\n        run: |\n          mkdir build && cd build\n          cmake .. -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release \\\n            -DCMAKE_CXX_STANDARD=14\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4\n      - name: Test\n        working-directory: ./build\n        run: ctest -LE flaky\n\n  build-windows-x86:\n    name: Windows x86 (32-bit)\n    runs-on: windows-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Configure\n        run: |\n          mkdir build && cd build\n          cmake .. -A Win32 -DDISPENSO_BUILD_TESTS=ON\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4 --config Release\n      - name: Test\n        working-directory: ./build\n        run: ctest -LE flaky --build-config Release\n\n  #############################################################################\n  # Sanitizer builds - critical for concurrency library\n  #############################################################################\n  sanitizers:\n    name: ${{ matrix.name }}\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          # TSan requires clang - GCC 13's TSan has spurious warnings about atomic_thread_fence\n          - name: Thread Sanitizer\n            cmake_args: -DTHREAD_SANITIZER=ON\n            cc: clang\n            cxx: clang++\n          - name: Address Sanitizer\n            cmake_args: -DADDRESS_SANITIZER=ON\n    steps:\n      - uses: actions/checkout@v4\n      - name: Configure\n        run: |\n          mkdir build && cd build\n          cmake .. -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug ${{ matrix.cmake_args }}\n        env:\n          CC: ${{ matrix.cc }}\n          CXX: ${{ matrix.cxx }}\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4\n      - name: Test\n        working-directory: ./build\n        run: ctest -LE flaky\n\n  #############################################################################\n  # Documentation build\n  #############################################################################\n  docs:\n    name: Documentation\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install Doxygen\n        run: sudo apt-get update && sudo apt-get install -y doxygen graphviz\n      - name: Build documentation\n        working-directory: ./docs\n        run: doxygen Doxyfile\n      - name: Check for warnings\n        working-directory: ./docs\n        run: |\n          if [ -s doxygen_warnings.log ]; then\n            echo \"Doxygen warnings found:\"\n            cat doxygen_warnings.log\n            exit 1\n          fi\n          echo \"No Doxygen warnings.\"\n\n  #############################################################################\n  # Code coverage\n  #############################################################################\n  coverage:\n    name: Code Coverage\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install lcov\n        run: sudo apt-get update && sudo apt-get install -y lcov\n      - name: Configure with coverage\n        run: |\n          mkdir build && cd build\n          cmake .. -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug \\\n            -DCMAKE_CXX_FLAGS=\"--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic\" \\\n            -DCMAKE_C_FLAGS=\"--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic\" \\\n            -DCMAKE_EXE_LINKER_FLAGS=\"--coverage\"\n      - name: Build\n        working-directory: ./build\n        run: cmake --build . --parallel 4\n      - name: Test (stable tests)\n        working-directory: ./build\n        run: ctest -LE flaky\n      - name: Test (TimedTask, with retries)\n        working-directory: ./build\n        run: ctest -L flaky -R \"^TimedTaskTest\\.\" --repeat until-pass:5\n      - name: Generate coverage report\n        run: |\n          lcov --capture --directory build --output-file coverage.info --ignore-errors mismatch,gcov,negative\n          lcov --remove coverage.info '/usr/*' '*/build/_deps/*' '*/tests/*' '*/third-party/*' '*/benchmarks/*' '*/examples/*' '*/bits/*' '*/ext/*' --output-file coverage.info --ignore-errors unused\n          lcov --list coverage.info\n      - name: Upload to Codecov\n        uses: codecov/codecov-action@v5\n        with:\n          files: coverage.info\n          token: ${{ secrets.CODECOV_TOKEN }}\n          fail_ci_if_error: false\n          verbose: true\n"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "name: CodeQL\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: '17 9 * * 1'\n\njobs:\n  analyze:\n    name: Analyze (C/C++)\n    runs-on: ubuntu-latest\n    permissions:\n      security-events: write\n      contents: read\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v4\n        with:\n          languages: c-cpp\n\n      - name: Build\n        run: |\n          cmake -S . -B build \\\n            -DDISPENSO_BUILD_TESTS=OFF \\\n            -DDISPENSO_BUILD_BENCHMARKS=OFF \\\n            -DCMAKE_BUILD_TYPE=Release\n          cmake --build build --parallel 4\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v4\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    branches: [ main ]\n\npermissions:\n  contents: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Set version from CHANGELOG\n      run: |\n        VERSION=$(grep -m1 '^[0-9]' CHANGELOG.md | sed 's/ .*//')\n        sed -i \"s/^PROJECT_NUMBER.*/PROJECT_NUMBER         = $VERSION/\" docs/Doxyfile\n\n    - name: Doxygen Action\n      uses: mattnotmitt/doxygen-action@v1\n      with:\n        working-directory: \"docs/\"\n        doxyfile-path: \"./Doxyfile\"\n\n\n    - name: Fix Doxygen output permissions and copy benchmark dashboard\n      run: |\n        sudo chown -R $(id -u):$(id -g) docs/doxygen\n        cp -r docs/benchmarks docs/doxygen/html/benchmarks\n\n    - name: Deploy\n      uses: peaceiris/actions-gh-pages@v4\n      with:\n        github_token: ${{ secrets.GITHUB_TOKEN }}\n        publish_dir: ./docs/doxygen/html\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled source #\n###################\n*.com\n*.class\n*.dll\n*.exe\n*.o\n*.so\n*.a\nbin\nlib\n\n# Packages #\n############\n# it's better to unpack these files and commit the raw source\n# git has its own built in compression methods\n*.7z\n*.dmg\n*.gz\n*.iso\n*.jar\n*.rar\n*.tar\n*.zip\n/.project\n\n# generated cmake files #\n#########################\n*CMakeCache.txt\n*.log\n*.make\n*.cmake\nCMakeFiles\nMakefile\n*Dir\n\n/build/*\ndocs/doxygen/\n\n# Clang #\n#########\n.cache/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "1.5.1 (March 28, 2026)\n\n### Bug fixes\n* Fixed `__ulock_wait`/`__ulock_wake` usage on macOS versions prior to 10.12 and on PowerPC where these APIs are unavailable. The ulock path is now guarded behind a runtime version check with `pthread_cond` fallback.\n* Fixed ARM64 Windows build failure: `notifier_common.h` incorrectly defined `_ARM_` (32-bit ARM) instead of `_ARM64_` on ARM64 Windows, causing `winnt.h` to reference missing 32-bit ARM intrinsics.\n* Fixed `platform.h` version macros not being updated for 1.5.0 release (were stuck at 1.4.1)\n* Removed vestigial `CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` from CMakeLists.txt. All public APIs now use proper `DISPENSO_DLL_ACCESS` annotations; the blanket export is no longer needed and is prohibited by vcpkg's maintainer guide.\n\n### Build system\n* Added `DISPENSO_USE_SYSTEM_CONCURRENTQUEUE` CMake option to use system-installed `moodycamel::concurrentqueue` instead of bundled copy (default OFF), for vcpkg compatibility\n* Export C++ standard requirement via `target_compile_features` so downstream consumers compile with at least the same standard dispenso was built with\n* Respect `BUILD_SHARED_LIBS` for `DISPENSO_SHARED_LIB` default, allowing vcpkg to control static/shared linkage\n\n### Infrastructure\n* Added package manager release automation script (`scripts/update_package_managers.py`) with post-write checksum verification, platform-aware testing, and PR body templates following each repo's CONTRIBUTING.md\n* Added CodeQL security analysis workflow scoped to main branch\n* Added package manager badges (vcpkg, Conan, Homebrew, MacPorts) to README\n* Added release checklist documentation\n\n1.5.0 (March 22, 2026)\n\n### New features\n* Added `SmallVector` container with configurable inline storage, reducing heap allocations for small collections\n* Added `SPSCRingBuffer` lock-free single-producer single-consumer ring buffer with power-of-two optimization\n* Added `scheduleBulk(count, generator)` API to ThreadPool, TaskSet, and ConcurrentTaskSet for efficient bulk task submission with reduced atomic contention\n* Added random-access iterator specialization for `for_each_n`, with iterator category dispatch for optimal chunk boundary computation\n* Added Mac futex-based wakeup using `os_sync_wait_on_address` (macOS 14.4+) with `__ulock_wait` fallback\n* Added C++20 concept constraints for better error messages when template requirements aren't met\n* Added experimental `fast_math` sublibrary with SIMD-accelerated math functions including `log2`, `exp2`, `exp`, `exp10`, `cbrt`, `sin`, `cos`, `sincos`, `asin`, and `atan2` with configurable accuracy/performance trade-offs and multiple SIMD backends (SSE4.1, AVX2, AVX512, NEON, Highway). **API unstable** — gated by `DISPENSO_BUILD_FAST_MATH` CMake option\n* Added benchmark runner and chart generation scripts with multi-platform support\n* Added interactive Plotly.js benchmark dashboard generator\n\n### Performance improvements\n* ThreadPool atomics simplification: replaced 3 per-task tracking atomics with `numSleeping_` + batched `workRemaining_` decrements, reducing per-task atomic operations from 5-6 to ~1 (+24% geometric mean across 568 benchmark tests)\n* ThreadPool wakeup heuristic: reduced futex calls from ~1M to ~11K by only waking when capacity cannot cover queued work; `mostly_idle` benchmark 2.6x faster\n* Cache-line alignment for `poolLoadFactor_` and `numThreads_` to reduce false sharing (L1 cache miss rate 16.33% → 6.92% on `schedule()` hot path)\n* Graph executor optimizations: `SmallVector` for node dependents, pre-reserve capacity, inline continuation (build_big_tree 1.95x faster, build_dep_chain 2.14x faster)\n* Serial pipeline SPSC optimization: dedicated executor with ring buffers for fully-serial pipelines (~33% faster)\n* Inline continuation for serial pipeline stages (scheduling overhead reduced ~3x)\n* Bulk wakeup with threshold-based `wakeN()`/`wakeAll()` selection for efficient bulk scheduling\n* `for_each_n` converted to `scheduleBulk`: 2.1x faster at 32 threads, 1.6x at 64 threads for 100M elements\n* `parallel_for` kAuto bulk scheduling: trivial_compute 52ms → 19ms at 192 threads (matching TBB)\n* ConcurrentVector: non-atomic buffer pointer cache for read-hot paths (disabled on ARM), inline asm `bsr` for `detail::log2` on x86, and platform-adaptive `bucketAndSubIndexForIndex` fast path\n* `OnceFunction` devirtualized: replaced vtable-based dispatch with direct function pointer, eliminating indirect call overhead\n* `TaskSet`/`ConcurrentTaskSet` noWait path: replaced `shared_ptr<Atomic>` with pool-allocated single-atomic chunk index, reducing allocation overhead\n\n### Infrastructure\n* Benchmark runner (`run_benchmarks.py`) with JSON output and machine info collection\n* Chart generator (`generate_charts.py`) with specialized visualizations per benchmark suite\n* Multi-platform benchmark composition (`update_benchmarks.py --compose`) for unified documentation\n* Prefer system-installed GoogleTest, Taskflow, and TBB in CMake with FetchContent fallback\n* Added oneTBB compatibility via `tbb_compat.h` wrapper for `task_scheduler_init`\n* Added BUCK targets for `idle_pool_benchmark`, `nested_pool_benchmark`, `for_each_benchmark`, and `locality_benchmark`\n\n### Documentation\n* Added examples directory with compilable example programs for each feature\n* Added Getting Started guide (`docs/getting_started.md`) with inline code snippets from examples\n* Added OpenMP migration guide (`docs/migrating_from_openmp.md`)\n* Improved README clarity, discoverability, and feature descriptions\n\n### CI and build improvements\n* Comprehensive CI matrix: 11 jobs covering 3 architectures (x64, x86, ARM64), 3 OSes, 3 compilers (GCC, Clang, MSVC), C++14/20, TSan/ASan, code coverage, and Doxygen builds\n* Added codecov.yml for enforcing 92% code coverage threshold\n\n### Bug fixes\n* Fixed ABI mismatch between exception and no-exception builds: `TaskSetBase` and `FutureImplResultMember` had conditionally compiled members that shifted struct layout depending on `-fno-exceptions`, causing crashes when translation units disagreed. Exception-related data members are now always present in the layout (with zero runtime cost when exceptions are disabled). **Note:** this changes the ABI for builds that previously used `-fno-exceptions`; recompile all code against 1.5 headers if mixing exception modes.\n* Fixed `ConcurrentTaskSet` parent stack overflow when tasks recursively schedule to the same task set: self-recursive inlining via `tryExecuteNext()` repeatedly pushed the same `TaskSetBase*` onto the thread-local parent stack (depth limit 64), causing an abort under heavy inlining. Fix skips redundant push/pop when the TaskSet is already the current parent.\n* Fixed pipeline `kLimited` scheduler `wait()` losing late-arriving items: the LIMITED path only drained the local queue without waiting for in-flight items, so items enqueued by a previous stage's CTS task after the drain could be permanently orphaned. Fix replaces the drain-only loop with an `outstanding_`-based spin that ensures all items complete, with `tryExecuteNext()` to keep the calling thread productive.\n* Fixed `parallel_for` with `kAuto` chunking incorrectly falling back to static chunking when `maxThreads` was left at default\n* Fixed `NoOpIter` missing iterator trait typedefs for C++20 compliance\n* Fixed `NoOpIter::operator*()` / `operator[]` static local data race\n* Fixed SmallBufferAllocator unsigned underflow where `allocSmallBuffer<1/2/3>()` returned nullptr instead of a 4-byte block\n* Fixed `cpuRelax()` being a no-op on MSVC (missing `_mm_pause()` / `__yield()` intrinsics)\n* Fixed x86 Windows build issues\n* Fixed Doxygen documentation warnings\n* Fixed pipeline exception safety: exceptions thrown in pipeline stage functors are now caught and propagated to the caller via `ConcurrentTaskSet`. Added RAII guards for stage resource cleanup, `OnceFunction::cleanupNotRun()` for proper deallocation of unexecuted tasks, and a deadlock fix in the `kLimited` scheduler's resource spin loop when exceptions leave no threads to release resources.\n* Fixed MSVC lambda capture for constexpr variable\n* Fixed `idle_pool_benchmark` fairness (loop bound, static scheduling, and pool placement)\n* Fixed `nested_for_benchmark` incorrect loop bound, static scheduling, and pool placement\n\n### Test improvements\n* Added comprehensive tests for thread_pool spin-poll with sleep mode\n* Added comprehensive task_set edge case tests\n* Added comprehensive tests for concurrent_object_arena\n* Added edge case tests for pool_allocator\n* Added timing tests for getTime() function\n* Added tests for Graph/Subgraph accessors and BiPropNode edge cases\n* Added `SmallVector` test suite (43 tests)\n* Added `SPSCRingBuffer` test suite (47 tests)\n* Improved overall test coverage from ~89% to 96.3% (dispenso source only, excluding stdlib and third-party)\n\n1.4.1 (January 5, 2026)\n\n### Bug fixes and build improvements\n* Fixed clock frequency calculation for mac-arm platforms\n* Addressed potential race condition at TimedTaskScheduler construction\n* Adjusted build platforms for better compatibility\n\n1.4 (January 2, 2025)\n\n### Efficiency improvements, bug and warning fixes\n* Added some benchmarks and comparison with TaskFlow (thanks andre-nguyen!)\n* Fixed compilation when compiling with DISPENSO_DEBUG (thanks EscapeZero!)\n* Improved efficiency on Linux for infrequent thread pool usage.  Reduces polling overhead by 10x by switching to event-based wakeup instead of spin polling.\n* Fix C++20 compilation issues (thanks aavbsouza!)\n* Fix several build warnings (thanks SeaOtocinclus!)\n* Add conda package badge, disable gtest install (thanks JeongSeok Lee!)\n* Solved rare post-main shutdown issues with NewThreadInvoker\n* Fixed test issues for 32-bit builds\n* Fixed broken test logic for test thread IDs\n* Fixed various build warnings\n\n1.3 (April 25, 2024)\n\n### Bug fixes, portability enhancements, and small functionality enhancements\n\n* Fixed several generic warnings (thanks michel-slm!)\n* cpuRelax added for PowerPC and ARM (thanks barracuda156!)\n* Added missing header (thanks ryandesign!)\n* Try to detect and add libatomic when required (thanks for discussions barracuda156!)\n* Enable small buffers from small buffer allocators to go down to 4 bytes (thanks for discussion David Caruso!).  This is handy for 32-bit builds where pointers are typically 4 bytes\n* Ensure that NOMINMAX is propagated for CMake Windows builds (thanks SeaOtocinclus!)\n* Fix some cases using std::make_shared for types requiring large alignment, which is a bug prior to C++17 (thanks for help finding these SeaOtocinclus!)\n* Set up CI on GitHub Actions, including builds for Mac and Windows in addition to Linux (thanks SeaOtocinclus!)\n* Add an envinronment variable `DISPENSO_MAX_THREADS_PER_POOL` to limit max number of threads available to any thread pool.  In the spirit of `OMP_NUM_THREADS`.  (thanks Yong-Chull Jang!)\n* Slight change of behavior w.r.t. use of `maxThreads` option in `ForEachOptions` and `ParForOptions` to limit concurrency the same way in both blocking and non-blocking `for_each` and `parallel_for` (thanks Arnie Yuan!)\n* Various fixes to enable CMake builds on various 32-bit platforms (thanks for discussions barracuda156!)\n* Updates to README\n\nKnown Issues:\n* Large subset of dispenso tests are known to fail on 32-bit PPC Mac.  If you have access to such a machine and are willing to help debug, it would be appreciated!\n* NewThreadInvoker can have a program shutdown race on Windows platforms if the threads launched by it are not finished running by end of main()\n\n1.2 (December 27, 2023)\n\n### Bug fixes and functionality enhancements\n\n* Several small bug fixes, especially around 32-bit builds and at-exit shutdown corner cases, and TSAN finding benign races and/or causing timeout due to pathological lock-free behaviors in newer versions of TSAN\n* Improve accuracy of `dispenso::getTime`\n* Add C++-20-like `Latch` functionality\n* Add mechanism for portable thread priorities\n* Add a timed task/periodically scheduled task feature.  Average and standard deviation of the accuracy of `dispenso::TimedTaskScheduler` are both much better than `folly::FunctionScheduler` (from 2x to 10x+ depending on settings and platform)\n* Enhancements to `parallel_for`\n  * Add an option that allows to automatically reduce the number of threads working on a range if the work is too cheap to justify parallelization.  This can result in 3000x+ speedups for very lightweight loops\n  * Resuse per-thread state containers across parallel for calls (these must block in-between, or be thread-safe types)\n  * `parallel_for` functors may now be called with an input range directly instead of requiring a ChunkedRange.  This is as simple as providing a functor/lambda that takes the additional argument, just as was previously done with `ChunkedRange`.  `ChunkedRange`s still work, and this is fully backward compatible\n* `ThreadPool`s have a new option for full spin polling.  This is generally best avoided, and I'd argue never to use this for the default Global thread pool, but can be useful for a subset of threads in systems that require real-time responsivity (especially, can be combined with the thread priority feature also found in this release)\n* Task graph execution (thanks Roman Fedotov!).  Building and running dispenso task graphs is typically 25% faster than the (already excellent) `TaskFlow` library in our benchmarks.  Additionally, we have a partial update feature that can enable much faster (e.g. 50x faster) execution in cases where only a small percentage of task inputs are updated (think of per-frame partial scene updates in a game)\n\n1.1 (October 1, 2022)\n\n### Performance and functionality enhancements\n\n* CMake changes to allow install of targets and CMake dispenso target exports (thanks jeffamstutz!)\n* Addition of typical container type definitions for ConcurrentVector (thanks Michael Jung!)\n* Large performance improvements for Futures and CompletionEvents on MacOs.  Resulted in order-of-magnitude speedups for those use cases on MacOs.\n* Addition of new benchmark for performance with infrequent use of `parallel_for`, `for_latency_benchmark`\n* Fixes to ensure `parallel_for` works with thread pools with zero threads (thanks kevinbchen!).  Further work has been done to ensure that thread pools with zero threads simply always run code inline.\n* By default, the global thread pool uses one fewer thread than the machine has hardware threads.  This behavior was introduced because dispenso very often runs on the calling thread as well as pool threads, and so one fewer thread in the pool can lead to better performance.\n* Update googletest version to 1.12.1 (thanks porumbes!)\n* Add a utility in dispenso to get a thread ID, `threadId`.  These 64-bit IDs are unique per thread, and will not be recyled.  These values grow from zero, ensuring the caller can assume they are small if number of threads also is small (e.g. you won't have an ID of `0xdeadbeef` if you only run hundreds or thousands of threads in the lifetime of the process).\n* Add a utility, `getTime`, to get time quickly.  This provides the double-precision time in seconds since the first call to `getTime` after process start.\n* Use a new scheduling mechanism in the thread pool when in Windows.  This resulted in up to a 13x improvement in latency between putting items in the pool and having those items run.  This scheduling is optional, but turned off for Linux and MacOs since scheduling was already fast on those platforms.\n* Optimizations to enable faster scheduling in thread pools.  This resulted in a range of 5% to 45% speedup across multiple benchmarks including `future_benchmark` and `pipeline_benchmark`.\n* Fixed a performance bug in work stealing logic; now dispenso outperforms TBB in the `pipeline_benchmark`\n* Added a task set cancellation feature, with a relatively simple mechanism for submitted work to check if it's owning task set has been cancelled.  When creating a task set, you can optionally opt into parent cancellation propagation as well.  While this propagation is fairly efficient, it did create a noticeable impact on performance in some cases, and thus it was decided to allow this behavior, but not penalize performance for those who don't need the behavior.\n\n1.0 (November 24, 2021)\n\n### dispenso initial release\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\ncmake_minimum_required(VERSION 3.12)\n\n# Use /Z7 (embedded debug info) instead of /Zi (PDB server) on MSVC+Ninja.\n# /Zi requires mspdbsrv.exe which can fail with C1902 \"Program database manager\n# mismatch\" when Ninja launches cl.exe as a subprocess.\nif(POLICY CMP0141)\n  cmake_policy(SET CMP0141 NEW)\n  set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT \"$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>\")\nendif()\n\n# CMake 4.x enables C++20 module scanning by default with Ninja, which breaks\n# try_compile() checks. Dispenso doesn't use C++20 modules.\nif(POLICY CMP0155)\n  cmake_policy(SET CMP0155 OLD)\nendif()\nset(CMAKE_CXX_SCAN_FOR_MODULES OFF)\n\nproject(\n  Dispenso\n  VERSION 1.5.1\n  DESCRIPTION \"Dispenso is a library for working with sets of parallel tasks\"\n  LANGUAGES CXX)\n\nif (\"${CMAKE_SOURCE_DIR}\" STREQUAL \"${CMAKE_CURRENT_SOURCE_DIR}\")\n  set(DISPENSO_STANDALONE TRUE)\nelse()\n  set(DISPENSO_STANDALONE FALSE)\nendif()\n\nif (DISPENSO_STANDALONE)\n  include(GNUInstallDirs)\nendif()\n\nlist(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)\n\n# Main project setup\nif(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)\n  set(CMAKE_CXX_EXTENSIONS OFF)\n  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)\n\n  # Default to BUILD_SHARED_LIBS when set (e.g. by vcpkg), otherwise ON.\n  if(DEFINED BUILD_SHARED_LIBS)\n    option(DISPENSO_SHARED_LIB \"Build Dispenso shared library\" ${BUILD_SHARED_LIBS})\n  else()\n    option(DISPENSO_SHARED_LIB \"Build Dispenso shared library\" ON)\n  endif()\n\nendif()\n\noption(ADDRESS_SANITIZER \"Use Address Sanitizer, incompatible with THREAD_SANITIZER\" OFF)\noption(THREAD_SANITIZER \"Use Thread Sanitizer, incompatible with ADDRESS_SANITIZER\" OFF)\n\nif (ADDRESS_SANITIZER)\n  add_compile_options(-fsanitize=address -fsanitize=undefined)\n  add_link_options(-fsanitize=address -fsanitize=undefined)\nelseif (THREAD_SANITIZER)\n  add_compile_options(-fsanitize=thread)\n  add_link_options(-fsanitize=thread)\nendif()\n\nset(CMAKE_CXX_STANDARD 14 CACHE STRING \"the C++ standard to use for this project\")\n\nset(DISPENSO_USE_SYSTEM_CONCURRENTQUEUE OFF CACHE BOOL\n    \"Use system-installed moodycamel::concurrentqueue instead of bundled copy\")\n\n###########################################################\n# Targets\nadd_subdirectory(dispenso)\n\nset(DISPENSO_BUILD_TESTS OFF CACHE BOOL \"Should tests be built?\")\nset(DISPENSO_BUILD_BENCHMARKS OFF CACHE BOOL \"Should benchmarks be built?\")\nset(DISPENSO_BUILD_EXAMPLES OFF CACHE BOOL \"Should examples be built?\")\nset(DISPENSO_BUILD_FAST_MATH OFF CACHE BOOL \"Build experimental fast_math sublibrary (API unstable)\")\nset(DISPENSO_FAST_MATH_SIMD \"none\" CACHE STRING \"SIMD ISA for fast_math targets: none, native, sse4.1, avx2, avx512, neon\")\nset(DISPENSO_FAST_MATH_HIGHWAY OFF CACHE BOOL \"Enable Highway SIMD backend for fast_math (fetches Highway if not found)\")\n\nif(DISPENSO_BUILD_FAST_MATH)\n  # Set compiler flags for the chosen SIMD backend.\n  # Each level is cumulative: avx2 implies sse4.1, avx512 implies avx2+sse4.1.\n  # \"native\" auto-detects all ISA extensions supported by the build machine.\n  set(DISPENSO_FAST_MATH_SIMD_FLAGS \"\")\n  if(DISPENSO_FAST_MATH_SIMD STREQUAL \"native\")\n    if(MSVC)\n      # MSVC doesn't have -march=native; AVX2 is the best portable flag.\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS /arch:AVX2)\n    else()\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS -march=native)\n    endif()\n  elseif(DISPENSO_FAST_MATH_SIMD STREQUAL \"sse4.1\")\n    if(NOT MSVC)\n      # MSVC enables SSE4.1 by default on x64.\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS -msse4.1)\n    endif()\n  elseif(DISPENSO_FAST_MATH_SIMD STREQUAL \"avx2\")\n    if(MSVC)\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS /arch:AVX2)\n    else()\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS -msse4.1 -mavx2 -mfma)\n    endif()\n  elseif(DISPENSO_FAST_MATH_SIMD STREQUAL \"avx512\")\n    if(MSVC)\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS /arch:AVX512)\n    else()\n      set(DISPENSO_FAST_MATH_SIMD_FLAGS -msse4.1 -mavx2 -mfma -mavx512f -mavx512bw -mavx512dq)\n    endif()\n  elseif(DISPENSO_FAST_MATH_SIMD STREQUAL \"neon\")\n    # NEON is implicit on aarch64; no extra flags needed.\n  elseif(NOT DISPENSO_FAST_MATH_SIMD STREQUAL \"none\")\n    message(FATAL_ERROR \"Unknown DISPENSO_FAST_MATH_SIMD value: ${DISPENSO_FAST_MATH_SIMD}. \"\n      \"Valid options: none, native, sse4.1, avx2, avx512, neon\")\n  endif()\n\n  # Find or fetch Highway if requested.\n  if(DISPENSO_FAST_MATH_HIGHWAY)\n    find_package(hwy QUIET)\n    if(NOT hwy_FOUND)\n      include(FetchContent)\n      FetchContent_Declare(\n        highway\n        GIT_REPOSITORY https://github.com/google/highway.git\n        GIT_TAG        1.2.0\n      )\n      set(HWY_ENABLE_TESTS OFF CACHE BOOL \"\" FORCE)\n      set(HWY_ENABLE_EXAMPLES OFF CACHE BOOL \"\" FORCE)\n      set(HWY_ENABLE_CONTRIB OFF CACHE BOOL \"\" FORCE)\n      FetchContent_MakeAvailable(highway)\n    endif()\n  endif()\nendif()\n\nif(DISPENSO_BUILD_TESTS)\n  enable_testing()\n  add_subdirectory(tests)\nendif()\n\nif(DISPENSO_BUILD_BENCHMARKS)\n  # Sadly any given release of folly seems to have some problem or another.  Leave disabled by default.\n  set(BENCHMARK_WITHOUT_FOLLY ON CACHE BOOL \"Should folly benchmarks be disabled?\")\n  add_subdirectory(benchmarks)\nendif()\n\nif(DISPENSO_BUILD_EXAMPLES)\n  add_subdirectory(examples)\nendif()\n"
  },
  {
    "path": "CMakePresets.json",
    "content": "{\n  \"version\": 6,\n  \"cmakeMinimumRequired\": {\n    \"major\": 3,\n    \"minor\": 21,\n    \"patch\": 0\n  },\n  \"configurePresets\": [\n    {\n      \"name\": \"default\",\n      \"displayName\": \"Default (system packages)\",\n      \"description\": \"Basic build without vcpkg. Uses system-installed dependencies.\",\n      \"binaryDir\": \"${sourceDir}/build/${presetName}\",\n      \"cacheVariables\": {\n        \"CMAKE_CXX_STANDARD\": \"17\"\n      }\n    },\n    {\n      \"name\": \"vcpkg\",\n      \"displayName\": \"vcpkg\",\n      \"description\": \"Use vcpkg for dependencies (TBB, GoogleTest, benchmark, etc.)\",\n      \"binaryDir\": \"${sourceDir}/build/${presetName}\",\n      \"toolchainFile\": \"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\",\n      \"cacheVariables\": {\n        \"CMAKE_CXX_STANDARD\": \"17\"\n      }\n    },\n    {\n      \"name\": \"dev\",\n      \"displayName\": \"Development (tests + benchmarks)\",\n      \"description\": \"Build everything for development: tests, benchmarks, and examples.\",\n      \"inherits\": \"vcpkg\",\n      \"cacheVariables\": {\n        \"DISPENSO_BUILD_TESTS\": \"ON\",\n        \"DISPENSO_BUILD_BENCHMARKS\": \"ON\",\n        \"DISPENSO_BUILD_EXAMPLES\": \"ON\",\n        \"CMAKE_CXX_STANDARD\": \"20\"\n      }\n    },\n    {\n      \"name\": \"win-dev\",\n      \"displayName\": \"Windows Development (Ninja)\",\n      \"description\": \"Windows dev build using Ninja for fast single-config builds. Run from a VS Developer Command Prompt.\",\n      \"inherits\": \"dev\",\n      \"binaryDir\": \"$env{TEMP}/dispenso-build/${presetName}\",\n      \"generator\": \"Ninja\",\n      \"cacheVariables\": {\n        \"CMAKE_BUILD_TYPE\": \"Release\",\n        \"VCPKG_APPLOCAL_DEPS\": \"OFF\"\n      },\n      \"condition\": {\n        \"type\": \"equals\",\n        \"lhs\": \"${hostSystemName}\",\n        \"rhs\": \"Windows\"\n      }\n    },\n    {\n      \"name\": \"asan\",\n      \"displayName\": \"Address Sanitizer\",\n      \"inherits\": \"dev\",\n      \"cacheVariables\": {\n        \"ADDRESS_SANITIZER\": \"ON\"\n      }\n    },\n    {\n      \"name\": \"tsan\",\n      \"displayName\": \"Thread Sanitizer\",\n      \"inherits\": \"dev\",\n      \"cacheVariables\": {\n        \"THREAD_SANITIZER\": \"ON\"\n      }\n    }\n  ],\n  \"buildPresets\": [\n    {\n      \"name\": \"default\",\n      \"configurePreset\": \"default\",\n      \"configuration\": \"Release\"\n    },\n    {\n      \"name\": \"dev\",\n      \"configurePreset\": \"dev\",\n      \"configuration\": \"Release\"\n    },\n    {\n      \"name\": \"win-dev\",\n      \"configurePreset\": \"win-dev\"\n    }\n  ],\n  \"testPresets\": [\n    {\n      \"name\": \"dev\",\n      \"configurePreset\": \"dev\",\n      \"configuration\": \"Release\",\n      \"output\": {\n        \"outputOnFailure\": true\n      }\n    },\n    {\n      \"name\": \"win-dev\",\n      \"configurePreset\": \"win-dev\",\n      \"output\": {\n        \"outputOnFailure\": true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to make participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies within all project spaces, and it also applies when\nan individual is representing the project or its community in public spaces.\nExamples of representing a project or community include using an official\nproject e-mail address, posting via an official social media account, or acting\nas an appointed representative at an online or offline event. Representation of\na project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at <opensource-conduct@fb.com>. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to dispenso\nWe want to make contributing to this project as easy and transparent as\npossible.  There is a design ethos behind the library, so it is recommended to reach out via a GitHub \nissue on the project to discuss non-trivial changes you may wish to make.  These changes include, for \nexample, wanting to change existing API, wanting to furnish a new utility, or wanting to change \nunderlying behavior substantially.  Let's avoid situations where you put in a lot of hard work, only \nto have to change it substantially or get your pull request rejected.\n\n## Our Development Process\nThis library has another home inside Facebook repos.  From there it is subjected to regular continuous integration testing on many platforms, and used by many projects.\n\n## Pull Requests\nWe actively welcome your pull requests.\n\n1. Fork the repo and create your branch from `master`.\n2. If you've added code that should be tested, add tests.\n3. If you've changed APIs, update the documentation.\n4. Ensure the test suite passes.\n5. Utilize clang-format.\n6. If you haven't already, complete the Contributor License Agreement (\"CLA\").\n\n## Contributor License Agreement (\"CLA\")\nIn order to accept your pull request, we need you to submit a CLA. You only need\nto do this once to work on any of Facebook's open source projects.\n\nComplete your CLA here: <https://code.facebook.com/cla>\n\n## Issues\nWe use GitHub issues to track public bugs. Please ensure your description is\nclear and has sufficient instructions to be able to reproduce the issue.\n\nFacebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe\ndisclosure of security bugs. In those cases, please go through the process\noutlined on that page and do not file a public issue.\n\n## Coding Style  \n* 2 spaces for indentation rather than tabs\n* 100 character line length\n* Member variables have trailing underscore_\n* BigCamelCase for classes and structs, and smallCamelCase for functions and variables (exception is if you are trying to match a substantial part of a standard library interface).\n* [1TBS braces](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS))\n* Most of all, try to be consistent with the surrounding code.  We have automated tools that will\n  enforce clang-format style for some files (e.g. the C++ core) once we import your pull request\n  into our internal code reviewing tools.\n\n## License\nBy contributing to dispenso, you agree that your contributions will be licensed\nunder the LICENSE.md file in the root directory of this source tree.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Facebook, Inc. and its affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build and test](https://github.com/facebookincubator/dispenso/actions/workflows/build.yml/badge.svg)](https://github.com/facebookincubator/dispenso/actions/workflows/build.yml)\n[![Documentation](https://img.shields.io/badge/docs-online-blue)](https://facebookincubator.github.io/dispenso)\n[![codecov](https://codecov.io/gh/facebookincubator/dispenso/branch/main/graph/badge.svg)](https://codecov.io/gh/facebookincubator/dispenso)\n[![Conan Center](https://img.shields.io/conan/v/dispenso)](https://conan.io/center/recipes/dispenso)\n[![vcpkg](https://img.shields.io/vcpkg/v/dispenso)](https://vcpkg.io/en/package/dispenso)\n[![Homebrew](https://img.shields.io/homebrew/v/dispenso)](https://formulae.brew.sh/formula/dispenso)\n[![MacPorts](https://img.shields.io/badge/macports-dispenso-blue)](https://ports.macports.org/port/dispenso/)\n[![Anaconda-Server Badge](https://anaconda.org/conda-forge/dispenso/badges/version.svg)](https://anaconda.org/conda-forge/dispenso)\n\n# Dispenso\n\n**A high-performance C++ thread pool and parallel algorithms library**\n\nDispenso is a modern **C++ parallel computing library** that provides work-stealing thread pools, parallel for loops, futures, task graphs, and concurrent containers. It serves as a powerful **alternative to OpenMP and Intel TBB**, offering better nested parallelism, sanitizer-clean code, and explicit thread pool control. Dispenso is used in hundreds of projects at Meta (formerly Facebook) and has been heavily tested and iterated on in production.\n\n**Key advantages over OpenMP and TBB:**\n- **No thread explosion** with nested parallel loops - dispenso's work-stealing prevents deadlocks and oversubscription\n- **Clean with ASAN/TSAN** - fully sanitizer-compatible, unlike many TBB versions\n- **Thread-safe shared futures** - `std::experimental::shared_future`-like API that TBB lacks, safe for multiple concurrent waiters, with much better performance than `std::future`\n- **Portable** - C++14 compatible with no compiler-specific pragmas or extensions; C++20 builds gain concept constraints for clearer error messages\n\n## Table of Contents\n\n- [Choose Dispenso If...](#choosedispenso)\n- [Features](#features)\n- [Quick Start](#quickstart)\n- [Comparison vs Other Libraries](#comparison)\n- [Migration Guides](#migrationguides)\n- [When Not to Use Dispenso](#nottouse)\n- [Documentation and Examples](#examples)\n- [Benchmark Results](#benchresults)\n- [Installing](#installing)\n- [Building](#building)\n- [Known Issues](#knownissues)\n- [License](#license)\n\n<div id='choosedispenso'/>\n\n## Choose Dispenso If...\n\n- You need **nested parallelism** without thread explosion\n- You want **sanitizer-clean** (ASAN/TSAN) concurrent code\n- You want **explicit control over thread pools** rather than implicit global state\n- You need **compute-bound futures**, not I/O-bound async\n- You want **stable APIs** and minimal dependencies\n- You need **cross-platform portability** from a C++14 baseline\n- You have **multiple independent parallel loops** that can overlap (cascading `parallel_for`)\n\n<div id='features'/>\n\n## Features\n\nDispenso provides a comprehensive set of parallel programming primitives:\n\n**Core runtime:**\n* **[`ThreadPool`](https://facebookincubator.github.io/dispenso/classdispenso_1_1_thread_pool.html)** — work-stealing thread pool backing all dispenso parallelism\n* **[`TaskSet`](https://facebookincubator.github.io/dispenso/classdispenso_1_1_task_set.html) / [`ConcurrentTaskSet`](https://facebookincubator.github.io/dispenso/classdispenso_1_1_concurrent_task_set.html)** — task grouping with wait, cancellation, and recursive scheduling\n\n**Parallel algorithms:**\n* **[`parallel_for`](docs/getting_started.md#your-first-parallel-loop)** — parallel loops over indices, blocking or non-blocking (cascaded); cascading `parallel_for` enables overlapping independent loops without oversubscription\n* **[`for_each`](docs/getting_started.md#parallel-iteration-with-for_each)** — parallel `std::for_each` / `std::for_each_n`\n* **[`Future`](docs/getting_started.md#futures-for-async-results)** — high-performance thread-safe shared futures with `then()`, `when_all()`, and an API matching `std::experimental::shared_future`\n* **[`Graph`](docs/getting_started.md#task-graphs)** — task graph execution with subgraph support and incremental re-evaluation\n* **[`pipeline`](docs/getting_started.md#pipelines)** — parallel pipelining of streaming workloads\n\n**Concurrent containers and synchronization:**\n* **[`ConcurrentVector`](docs/getting_started.md#concurrentvector)** — concurrent growable vector, superset of TBB `concurrent_vector` API\n* **[`Latch`](docs/getting_started.md#latch)** — one-shot barrier for thread synchronization\n* **[`RWLock`](https://facebookincubator.github.io/dispenso/classdispenso_1_1_r_w_lock.html)** — reader-writer spin lock, outperforms `std::shared_mutex` under low write contention\n* **`SPSCRingBuffer`** — lock-free single-producer single-consumer ring buffer *(1.5.0)*\n\n**General-purpose utilities:**\n* **`SmallVector`** — inline-storage vector (not thread-aware; similar to `folly::small_vector`) *(1.5.0)*\n* **`OnceFunction`** — lightweight move-only `void()` callable\n* **`PoolAllocator`** — pool allocator with pluggable backing allocation (e.g. CUDA)\n* **`SmallBufferAllocator`** — fast concurrent allocation for temporary objects\n* **[`ResourcePool`](docs/getting_started.md#resource-pooling)** — semaphore-like guard around pooled resources\n* **`CompletionEvent`** — notifiable event with wait and timed wait\n* **`AsyncRequest`** — lightweight constrained message passing\n* **`ConcurrentObjectArena`** — fast same-type object arena\n\n<div id='quickstart'/>\n\n## Quick Start\n\n**Parallel for loop** - the most common use case:\n\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Sequential\nfor (size_t i = 0; i < N; ++i) {\n    process(data[i]);\n}\n\n// Parallel with dispenso - just wrap it!\ndispenso::parallel_for(0, N, [&](size_t i) {\n    process(data[i]);\n});\n```\n\n**Install via your favorite package manager:**\n\n```bash\n# Conda\nconda install -c conda-forge dispenso\n\n# Fedora/RHEL\nsudo dnf install dispenso-devel\n\n# Or build from source (see below)\n```\n\n<div id='comparison'/>\n\n## Comparison vs Other Libraries\n\n### TBB (Intel Threading Building Blocks)\n\nTBB has more functionality overall, but we built dispenso for three reasons:\n1. **Sanitizer compatibility** — TBB doesn't work well with ASAN/TSAN\n2. **Thread-safe shared futures** — TBB lacks a futures interface; dispenso provides `std::experimental::shared_future`-like futures safe for multiple concurrent waiters\n3. **Non-Intel hardware** — we needed to control performance on diverse platforms\n\n**Performance:** Dispenso tends to be faster for small and medium parallel loops, and on par for large ones. When many loops run independently, dispenso's cascading `parallel_for` avoids oversubscription and has delivered **32-50% speedups in production workloads** after porting from TBB at Meta. TBB lacks an equivalent mechanism.\n\nSee [Migrating from TBB](docs/migrating_from_tbb.md) for a step-by-step porting guide.\n\n### OpenMP\n\nOpenMP has simple syntax for basic loops but grows complex for advanced constructs. Nested `#pragma omp parallel for` inside threaded code risks thread explosion and machine exhaustion. Dispenso outperforms OpenMP for medium and large loops. OpenMP has an advantage for very small loops due to direct compiler support, though dispenso's `minItemsPerChunk` option can close this gap by tuning the parallelism threshold for small/fast loops.\n\nSee [Migrating from OpenMP](docs/migrating_from_openmp.md) for a step-by-step porting guide.\n\n### Folly\n\nFolly excels at asynchronous I/O with coroutine support. Dispenso is designed for **compute-bound** work. Dispenso's futures are lighter-weight and faster for compute workloads; Folly is the better choice for I/O-heavy applications.\n\n### TaskFlow\n\nTaskFlow focuses on task graph execution. Dispenso has faster graph construction, faster full and partial graph execution, much lower `parallel_for` overhead (10-100x in benchmarks), and simpler/faster pipeline construction. TaskFlow does offer CUDA graph mappings, which dispenso does not currently provide.\n\n### Others (GCD, C++ std parallelism)\n\nGCD is Apple-specific with ports to other platforms. C++ parallel algorithms are still evolving — we are interested in enabling dispenso as a backend for `std::execution` and C++ coroutines. Contributions and benchmarks are welcome.\n\n<div id='migrationguides'/>\n\n### Migration Guides\n\n- **[Migrating from TBB](docs/migrating_from_tbb.md)** — API mappings, thread pool differences, and common porting patterns\n- **[Migrating from OpenMP](docs/migrating_from_openmp.md)** — Replacing `#pragma omp` with dispenso equivalents, handling reductions and nested parallelism\n\n<div id='nottouse'/>\n\n## When Not to Use Dispenso\nDispenso isn't really designed for high-latency task offload, it works best for compute-bound tasks.  Using the thread pool for networking, disk, or in cases with frequent TLB misses (really any scenario with kernel context switches) may result in less than ideal performance.\n\nIn these kernel context switch scenarios, `dispenso::Future` can be used with `dispenso::NewThreadInvoker`, which should be roughly equivalent with std::future performance.\n\nIf you need async I/O, Folly is likely a good choice (though it still doesn't fix e.g. TLB misses).\n\n<div id='examples'/>\n\n## Documentation and Examples\n[Documentation can be found here](https://facebookincubator.github.io/dispenso)\n\nHere are some simple examples of what you can do in dispenso. See tests and benchmarks for more examples.\n\n### parallel\\_for\n\nA simple sequential loop can be parallelized with minimal changes:\n\n```cpp\nfor(size_t j = 0; j < kLoops; ++j) {\n  vec[j] = someFunction(j);\n}\n```\n\nBecomes:\n\n```cpp\ndispenso::parallel_for(0, kLoops, [&vec] (size_t j) {\n  vec[j] = someFunction(j);\n});\n```\n\n### TaskSet\n\nSchedule multiple tasks and wait for them to complete:\n\n```cpp\nvoid randomWorkConcurrently() {\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n  tasks.schedule([&stateA]() { stateA = doA(); });\n  tasks.schedule([]() { doB(); });\n  // Do some work on current thread\n  tasks.wait(); // After this, A, B done.\n  tasks.schedule(doC);\n  tasks.schedule([&stateD]() { doD(stateD); });\n} // TaskSet's destructor waits for all scheduled tasks to finish\n```\n\n### ConcurrentTaskSet\n\nBuild a tree in parallel using recursive task scheduling:\n\n```cpp\nstruct Node {\n  int val;\n  std::unique_ptr<Node> left, right;\n};\nvoid buildTree(dispenso::ConcurrentTaskSet& tasks, std::unique_ptr<Node>& node, int depth) {\n  if (depth) {\n    node = std::make_unique<Node>();\n    node->val = depth;\n    tasks.schedule([&tasks, &left = node->left, depth]() { buildTree(tasks, left, depth - 1); });\n    tasks.schedule([&tasks, &right = node->right, depth]() { buildTree(tasks, right, depth - 1); });\n  }\n}\nvoid buildTreeParallel() {\n  std::unique_ptr<Node> root;\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  buildTree(tasks, root, 20);\n  tasks.wait();  // tasks would also wait here in destructor if we omitted this line\n}\n```\n\n### Future\n\nCompose asynchronous operations with futures:\n\n```cpp\ndispenso::Future<size_t> ThingProcessor::processThings() {\n  auto expensiveFuture = dispenso::async([this]() {\n    return processExpensiveThing(expensive_);\n  });\n  auto futureOfManyCheap = dispenso::async([this]() {\n    size_t sum = 0;\n    for (auto &thing : cheapThings_) {\n      sum += processCheapThing(thing);\n    }\n    return sum;\n  });\n  return dispenso::when_all(expensiveFuture, futureOfManyCheap).then([](auto &&tuple) {\n    return std::get<0>(tuple).get() + std::get<1>(tuple).get();\n  });\n}\n\nauto result = thingProc->processThings();\nuseResult(result.get());\n```\n\n### ConcurrentVector\n\nSafely grow a vector from multiple threads:\n\n```cpp\nConcurrentVector<std::unique_ptr<int>> values;\ndispenso::parallel_for(\n  dispenso::makeChunkedRange(0, length, dispenso::ParForChunking::kStatic),\n  [&values](int i, int end) {\n    values.grow_by_generator(end - i, [i]() mutable { return std::make_unique<int>(i++); });\n  });\n```\n\n<div id='benchresults'/>\n\n## Benchmark Results\n\nDispenso is benchmarked across Linux (x64), macOS (ARM64), Windows (x64), and Android (ARM64),\ncomparing against OpenMP, TBB, TaskFlow, folly, and `std::async` across thread pools, parallel\nloops, futures, graphs, concurrent containers, and more.\n\n**[Interactive Benchmark Dashboard](https://facebookincubator.github.io/dispenso/benchmarks/)** — explore all results\nwith platform switching, dark/light theme, and detailed per-benchmark charts.\n\n<div id='installing'/>\n\n## Installing\nBinary builds of Dispenso are available through several package managers:\n\n- **Conda**: `conda install -c conda-forge dispenso`\n- **Conan**: `conan install --requires=dispenso/1.5.0`\n- **vcpkg**: `vcpkg install dispenso`\n- **Homebrew**: `brew install dispenso`\n- **MacPorts**: `sudo port install dispenso`\n- **Fedora/RHEL**: `sudo dnf install dispenso-devel`\n\nIf your platform is not on the list, see [the next section](#building) for instructions to build from source.\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/dispenso.svg)](https://repology.org/project/dispenso/versions)\n\n<div id='building'/>\n\n## Building\n\n**Linux and macOS:**\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT\nmake -j\n```\n\n**Windows** (from Developer Command Prompt):\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT\ncmake --build . --config Release\n```\n\nFor detailed instructions including CMake prerequisites, installation, testing, and\nbenchmarking, see [docs/building.md](docs/building.md).\n\n<div id='knownissues'/>\n\n## Known Issues\n\n* A subset of dispenso tests are known to fail on 32-bit PPC Mac.  If you have access to such a machine and are willing to help debug, it would be appreciated!\n\n## TODO\n* Enable Windows benchmarks through CMake. *(may be resolved soon — actively being worked on)*\n\n<div id='license'/>\n\n## License\n\nThe library is released under the MIT license, but also relies on the (excellent) moodycamel concurrentqueue library, which is released under the Simplified BSD and Zlib licenses.  See the top of the source at `dispenso/third-party/moodycamel/*.h` for details.\n"
  },
  {
    "path": "benchmarks/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.12)\n\n\n# Try to find Taskflow: system install, DISPENSO_DEPS_DIR, ~/dispenso_deps, then FetchContent.\nfind_package(Taskflow QUIET)\nif(NOT Taskflow_FOUND)\n  # Check well-known local directories for a Taskflow source tree.\n  # Searches for both \"taskflow\" and versioned names like \"taskflow-3.11.0\".\n  if(DEFINED DISPENSO_DEPS_DIR)\n    file(GLOB _taskflow_dep_candidates \"${DISPENSO_DEPS_DIR}/taskflow*\")\n    list(APPEND _taskflow_search_dirs ${_taskflow_dep_candidates})\n  endif()\n  file(GLOB _taskflow_home_candidates \"$ENV{HOME}/dispenso_deps/taskflow*\")\n  list(APPEND _taskflow_search_dirs ${_taskflow_home_candidates})\n\n  set(_taskflow_local_dir \"\")\n  foreach(_dir ${_taskflow_search_dirs})\n    if(EXISTS \"${_dir}/taskflow/taskflow.hpp\")\n      set(_taskflow_local_dir \"${_dir}\")\n      break()\n    endif()\n  endforeach()\n\n  if(_taskflow_local_dir)\n    message(STATUS \"Found local Taskflow at ${_taskflow_local_dir}\")\n    add_library(taskflow INTERFACE)\n    target_include_directories(taskflow INTERFACE \"${_taskflow_local_dir}\")\n  else()\n    message(STATUS \"Taskflow not found locally, fetching from GitHub...\")\n    include(FetchContent)\n    message(STATUS \"Using up-to-date taskflow\")\n    FetchContent_Declare(\n      taskflow\n      GIT_REPOSITORY https://github.com/taskflow/taskflow.git\n      GIT_TAG        v3.6.0\n      CONFIGURE_COMMAND \"\"\n      BUILD_COMMAND \"\"\n    )\n    FetchContent_GetProperties(taskflow)\n    if(NOT taskflow_POPULATED)\n      FetchContent_Populate(taskflow)\n    endif()\n    FetchContent_MakeAvailable(taskflow)\n    add_library(taskflow INTERFACE)\n    target_include_directories(taskflow INTERFACE ${taskflow_SOURCE_DIR})\n  endif()\nelse()\n  message(STATUS \"Found system Taskflow\")\n  if(NOT TARGET taskflow)\n    add_library(taskflow INTERFACE)\n    target_link_libraries(taskflow INTERFACE Taskflow::Taskflow)\n  endif()\nendif()\n\nfind_package(benchmark QUIET)\nif(NOT benchmark_FOUND)\n  message(STATUS \"Google Benchmark not found locally, fetching from GitHub...\")\n  include(FetchContent)\n  FetchContent_Declare(\n    benchmark\n    GIT_REPOSITORY https://github.com/google/benchmark.git\n    GIT_TAG        v1.8.3\n  )\n  set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL \"Disable benchmark tests\")\n  set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL \"Disable gtest tests\")\n  FetchContent_MakeAvailable(benchmark)\nelse()\n  message(STATUS \"Found system Google Benchmark\")\nendif()\n# OpenMP support (including Windows/MSVC)\nfind_package(OpenMP)\n\n# TBB support - prefer CONFIG mode to find TBBConfig.cmake from vcpkg/modern installs\nfind_package(TBB CONFIG QUIET)\nif(NOT TBB_FOUND)\n  # Fall back to old FindTBB.cmake module\n  find_package(TBB QUIET)\nendif()\n\nfind_package(folly)\n\nif (WIN32)\n  set (REQUIRED_LIBS dispenso benchmark::benchmark benchmark::benchmark_main taskflow)\nelse (WIN32)\n  set (REQUIRED_LIBS dispenso benchmark::benchmark benchmark::benchmark_main pthread taskflow)\nendif (WIN32)\n\nif (TBB_FOUND)\n  # Handle both old TBB (lowercase 'tbb' target) and new oneTBB (TBB::tbb target)\n  if(TARGET TBB::tbb)\n    set (OPTIONAL_LIBS ${OPTIONAL_LIBS} TBB::tbb)\n  elseif(TARGET tbb)\n    set (OPTIONAL_LIBS ${OPTIONAL_LIBS} tbb)\n  else()\n    set (OPTIONAL_LIBS ${OPTIONAL_LIBS} TBB::tbb)\n  endif()\nelse (TBB_FOUND)\n  add_compile_definitions(BENCHMARK_WITHOUT_TBB)\nendif (TBB_FOUND)\n\nif (OpenMP_CXX_FOUND)\n  set (OPTIONAL_LIBS ${OPTIONAL_LIBS} OpenMP::OpenMP_CXX)\nendif (OpenMP_CXX_FOUND)\n\nif (FOLLY_LIBRARIES AND NOT ${BENCHMARK_WITHOUT_FOLLY})\n  find_package(gflags)\n  set (OPTIONAL_LIBS ${OPTIONAL_LIBS} ${FOLLY_LIBRARIES})\nelse (FOLLY_LIBRARIES AND NOT ${BENCHMARK_WITHOUT_FOLLY})\n  add_compile_definitions(BENCHMARK_WITHOUT_FOLLY)\nendif (FOLLY_LIBRARIES AND NOT ${BENCHMARK_WITHOUT_FOLLY})\n\nfile(GLOB BENCHMARK_FILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/benchmarks/*.cpp)\n\nforeach(BENCHMARK_FILE ${BENCHMARK_FILES})\n  set(BENCHMARK_NAME)\n  get_filename_component(BENCHMARK_NAME ${BENCHMARK_FILE} NAME_WE)\n  add_executable(${BENCHMARK_NAME} ${BENCHMARK_FILE})\n  target_compile_features(${BENCHMARK_NAME} PRIVATE cxx_std_20)\n  target_link_libraries(${BENCHMARK_NAME} ${REQUIRED_LIBS} ${OPTIONAL_LIBS})\nendforeach()\n\nif(DISPENSO_BUILD_FAST_MATH)\n  add_subdirectory(fast_math)\nendif()\n"
  },
  {
    "path": "benchmarks/benchmark_common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <benchmark/benchmark.h>\n\n#if defined(__GNUC__) || defined(__clang__)\n#define UNUSED_VAR myLocalForLoopVar __attribute__((unused))\n#elif defined(_MSC_VER)\n#define UNUSED_VAR myLocalForLoopVar __pragma(warning(suppress : 4100))\n#else\n#define UNUSED_VAR myLocalForLoopVar\n#endif\n"
  },
  {
    "path": "benchmarks/cascading_parallel_for_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Benchmark demonstrating dispenso's cascading parallel_for advantage.\n *\n * When multiple independent parallel_for loops need to run, dispenso can\n * overlap them on a shared TaskSet using ParForOptions{.wait = false}.\n * TBB and OpenMP each impose an implicit barrier per parallel_for call,\n * forcing sequential execution of independent loops.\n */\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#include <array>\n#include <unordered_map>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_for.h\"\n#include \"tbb/task_group.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nstatic constexpr int32_t kSmallSize = 1000;\nstatic constexpr int32_t kMediumSize = 100000;\nstatic constexpr int32_t kLargeSize = 10000000;\n\nstatic constexpr int32_t kNumLoops = 8;\n\n// Minimum work per chunk to amortize scheduling overhead for cheap lambdas.\n// With trivial compute (~4 integer ops ≈ 2ns/element), 512 elements ≈ 1µs\n// of work, comfortably covering task dispatch cost on Windows.\nstatic constexpr uint32_t kMinItemsPerChunk = 512;\n\nstatic uint32_t kSeed(42);\n\ninline int32_t compute(int32_t x) {\n  return x * x - 3 * x + 7;\n}\n\ninline int32_t fuse(const std::array<int32_t, kNumLoops>& values) {\n  int32_t result = 0;\n  for (int32_t k = 0; k < kNumLoops; ++k) {\n    result += values[static_cast<size_t>(k)];\n  }\n  return result;\n}\n\nstruct BenchArrays {\n  std::array<std::vector<int32_t>, kNumLoops> inputs;\n  std::array<std::vector<int32_t>, kNumLoops> outputs;\n  std::vector<int32_t> result;\n};\n\nBenchArrays& getArrays(int32_t numElements) {\n  static std::unordered_map<int32_t, BenchArrays> arrays;\n  auto it = arrays.find(numElements);\n  if (it != arrays.end()) {\n    return it->second;\n  }\n  srand(kSeed);\n  BenchArrays ba;\n  for (int32_t k = 0; k < kNumLoops; ++k) {\n    ba.inputs[static_cast<size_t>(k)].reserve(static_cast<size_t>(numElements));\n    for (int32_t i = 0; i < numElements; ++i) {\n      ba.inputs[static_cast<size_t>(k)].push_back((rand() & 255) - 127);\n    }\n    ba.outputs[static_cast<size_t>(k)].resize(static_cast<size_t>(numElements), 0);\n  }\n  ba.result.resize(static_cast<size_t>(numElements), 0);\n  auto res = arrays.emplace(numElements, std::move(ba));\n  assert(res.second);\n  return res.first->second;\n}\n\nvoid checkResults(BenchArrays& ba, int32_t numElements) {\n  for (int32_t i = 0; i < numElements; ++i) {\n    auto idx = static_cast<size_t>(i);\n    std::array<int32_t, kNumLoops> expected;\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      expected[static_cast<size_t>(k)] = compute(ba.inputs[static_cast<size_t>(k)][idx]);\n    }\n    int32_t expectedFused = fuse(expected);\n    if (ba.result[idx] != expectedFused) {\n      std::cerr << \"FAIL at index \" << i << \": got \" << ba.result[idx] << \" expected \"\n                << expectedFused << std::endl;\n      abort();\n    }\n  }\n}\n\nvoid BM_serial(benchmark::State& state) {\n  const int32_t numElements = state.range(0);\n  auto& ba = getArrays(numElements);\n\n  for (auto UNUSED_VAR : state) {\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      auto kk = static_cast<size_t>(k);\n      for (int32_t i = 0; i < numElements; ++i) {\n        ba.outputs[kk][static_cast<size_t>(i)] = compute(ba.inputs[kk][static_cast<size_t>(i)]);\n      }\n    }\n    for (int32_t i = 0; i < numElements; ++i) {\n      auto idx = static_cast<size_t>(i);\n      std::array<int32_t, kNumLoops> vals;\n      for (int32_t k = 0; k < kNumLoops; ++k) {\n        vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n      }\n      ba.result[idx] = fuse(vals);\n    }\n  }\n  checkResults(ba, numElements);\n}\n\nvoid BM_dispenso_blocking(benchmark::State& state) {\n  const int32_t numThreads = state.range(0) - 1;\n  const int32_t numElements = state.range(1);\n  auto& ba = getArrays(numElements);\n\n  dispenso::ThreadPool pool(numThreads);\n  dispenso::ParForOptions opts;\n  opts.minItemsPerChunk = kMinItemsPerChunk;\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      auto kk = static_cast<size_t>(k);\n      dispenso::parallel_for(\n          tasks,\n          0,\n          numElements,\n          [&inputs = ba.inputs[kk], &outputs = ba.outputs[kk]](int32_t i) {\n            outputs[static_cast<size_t>(i)] = compute(inputs[static_cast<size_t>(i)]);\n          },\n          opts);\n    }\n    dispenso::parallel_for(\n        tasks,\n        0,\n        numElements,\n        [&ba](int32_t i) {\n          auto idx = static_cast<size_t>(i);\n          std::array<int32_t, kNumLoops> vals;\n          for (int32_t k = 0; k < kNumLoops; ++k) {\n            vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n          }\n          ba.result[idx] = fuse(vals);\n        },\n        opts);\n  }\n  checkResults(ba, numElements);\n}\n\nvoid BM_dispenso_cascaded(benchmark::State& state) {\n  const int32_t numThreads = state.range(0) - 1;\n  const int32_t numElements = state.range(1);\n  auto& ba = getArrays(numElements);\n\n  dispenso::ThreadPool pool(numThreads);\n  dispenso::ParForOptions noWait;\n  noWait.wait = false;\n  noWait.minItemsPerChunk = kMinItemsPerChunk;\n  dispenso::ParForOptions opts;\n  opts.minItemsPerChunk = kMinItemsPerChunk;\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    // First N-1 loops: non-blocking, returns immediately\n    for (int32_t k = 0; k < kNumLoops - 1; ++k) {\n      auto kk = static_cast<size_t>(k);\n      dispenso::parallel_for(\n          tasks,\n          0,\n          numElements,\n          [&inputs = ba.inputs[kk], &outputs = ba.outputs[kk]](int32_t i) {\n            outputs[static_cast<size_t>(i)] = compute(inputs[static_cast<size_t>(i)]);\n          },\n          noWait);\n    }\n    // Last independent loop: blocking — calling thread participates,\n    // implicitly waits for all prior non-blocking loops too\n    {\n      constexpr auto kk = static_cast<size_t>(kNumLoops - 1);\n      dispenso::parallel_for(\n          tasks,\n          0,\n          numElements,\n          [&inputs = ba.inputs[kk], &outputs = ba.outputs[kk]](int32_t i) {\n            outputs[static_cast<size_t>(i)] = compute(inputs[static_cast<size_t>(i)]);\n          },\n          opts);\n    }\n    // Fusion: blocking (depends on all outputs being complete)\n    dispenso::parallel_for(\n        tasks,\n        0,\n        numElements,\n        [&ba](int32_t i) {\n          auto idx = static_cast<size_t>(i);\n          std::array<int32_t, kNumLoops> vals;\n          for (int32_t k = 0; k < kNumLoops; ++k) {\n            vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n          }\n          ba.result[idx] = fuse(vals);\n        },\n        opts);\n  }\n  checkResults(ba, numElements);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int32_t numThreads = state.range(0);\n  const int32_t numElements = state.range(1);\n  auto& ba = getArrays(numElements);\n\n  omp_set_num_threads(numThreads);\n\n  for (auto UNUSED_VAR : state) {\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      auto kk = static_cast<size_t>(k);\n#pragma omp parallel for\n      for (int32_t i = 0; i < numElements; ++i) {\n        ba.outputs[kk][static_cast<size_t>(i)] = compute(ba.inputs[kk][static_cast<size_t>(i)]);\n      }\n    }\n#pragma omp parallel for\n    for (int32_t i = 0; i < numElements; ++i) {\n      auto idx = static_cast<size_t>(i);\n      std::array<int32_t, kNumLoops> vals;\n      for (int32_t k = 0; k < kNumLoops; ++k) {\n        vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n      }\n      ba.result[idx] = fuse(vals);\n    }\n  }\n  checkResults(ba, numElements);\n}\n#endif /*defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int32_t numThreads = state.range(0);\n  const int32_t numElements = state.range(1);\n  auto& ba = getArrays(numElements);\n\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(numThreads);\n\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      auto kk = static_cast<size_t>(k);\n      tbb::parallel_for(\n          tbb::blocked_range<int32_t>(0, numElements),\n          [&inputs = ba.inputs[kk],\n           &outputs = ba.outputs[kk]](const tbb::blocked_range<int32_t>& r) {\n            for (int32_t i = r.begin(); i != r.end(); ++i) {\n              outputs[static_cast<size_t>(i)] = compute(inputs[static_cast<size_t>(i)]);\n            }\n          });\n    }\n    tbb::parallel_for(\n        tbb::blocked_range<int32_t>(0, numElements), [&ba](const tbb::blocked_range<int32_t>& r) {\n          for (int32_t i = r.begin(); i != r.end(); ++i) {\n            auto idx = static_cast<size_t>(i);\n            std::array<int32_t, kNumLoops> vals;\n            for (int32_t k = 0; k < kNumLoops; ++k) {\n              vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n            }\n            ba.result[idx] = fuse(vals);\n          }\n        });\n  }\n  checkResults(ba, numElements);\n}\n\n// TBB with task_group: launch all independent parallel_for loops concurrently\n// via task_group, then wait — emulating dispenso's cascading behavior.\nvoid BM_tbb_task_group(benchmark::State& state) {\n  const int32_t numThreads = state.range(0);\n  const int32_t numElements = state.range(1);\n  auto& ba = getArrays(numElements);\n\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(numThreads);\n    tbb::task_group tg;\n\n    for (int32_t k = 0; k < kNumLoops; ++k) {\n      auto kk = static_cast<size_t>(k);\n      tg.run([&inputs = ba.inputs[kk], &outputs = ba.outputs[kk], numElements]() {\n        tbb::parallel_for(\n            tbb::blocked_range<int32_t>(0, numElements),\n            [&inputs, &outputs](const tbb::blocked_range<int32_t>& r) {\n              for (int32_t i = r.begin(); i != r.end(); ++i) {\n                outputs[static_cast<size_t>(i)] = compute(inputs[static_cast<size_t>(i)]);\n              }\n            });\n      });\n    }\n    tg.wait();\n\n    tbb::parallel_for(\n        tbb::blocked_range<int32_t>(0, numElements), [&ba](const tbb::blocked_range<int32_t>& r) {\n          for (int32_t i = r.begin(); i != r.end(); ++i) {\n            auto idx = static_cast<size_t>(i);\n            std::array<int32_t, kNumLoops> vals;\n            for (int32_t k = 0; k < kNumLoops; ++k) {\n              vals[static_cast<size_t>(k)] = ba.outputs[static_cast<size_t>(k)][idx];\n            }\n            ba.result[idx] = fuse(vals);\n          }\n        });\n  }\n  checkResults(ba, numElements);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK(BM_serial)->Args({kSmallSize})->Args({kMediumSize})->Args({kLargeSize})->UseRealTime();\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif // OPENMP\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_tbb_task_group)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\nBENCHMARK(BM_dispenso_blocking)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_cascaded)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/concurrent_vector_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <deque>\n#include <iostream>\n#include <random>\n#include <vector>\n\n#include <benchmark/benchmark.h>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/concurrent_vector.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/parallel_for.h>\n\n#include \"thread_benchmark_common.h\"\n\nconstexpr size_t kLength = (1 << 20);\n\nvoid checkIotaSum(int64_t sum) {\n  if (sum != (static_cast<int64_t>(kLength - 1) * kLength) / 2) {\n    std::cout << sum << \" vs \" << ((kLength - 1) * kLength) / 2 << std::endl;\n\n    std::abort();\n  }\n}\n\ntemplate <typename Cont>\nvoid checkIotaSum(const Cont& c, int64_t sum) {\n  if (sum != (static_cast<int64_t>(kLength - 1) * kLength) / 2) {\n    std::cout << sum << \" vs \" << ((kLength - 1) * kLength) / 2 << std::endl;\n\n    std::vector<uint8_t> accountedFor(kLength);\n    for (auto v : c) {\n      accountedFor[v] = 1;\n    }\n\n    for (size_t i = 0; i < kLength; ++i) {\n      if (!accountedFor[i]) {\n        std::cout << \"missing \" << i << std::endl;\n      }\n    }\n\n    std::abort();\n  }\n}\n\ntemplate <typename ContainerInit>\nvoid pushBackImpl(benchmark::State& state, ContainerInit containerInit) {\n  for (auto UNUSED_VAR : state) {\n    auto values = containerInit();\n    for (size_t i = 0; i < kLength; ++i) {\n      values.push_back(i);\n    }\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\ntemplate <typename ContainerInit>\nvoid pushBackGrowByAlternativeTbb(benchmark::State& state, ContainerInit containerInit) {\n  for (auto UNUSED_VAR : state) {\n    auto values = containerInit();\n    auto it = values.grow_by(kLength);\n    auto end = values.end();\n    size_t i = 0;\n    for (; it != end; ++it) {\n      *it = i++;\n    }\n  }\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\ntemplate <typename ContainerInit>\nvoid pushBackGrowByAlternativeDispenso(benchmark::State& state, ContainerInit containerInit) {\n  for (auto UNUSED_VAR : state) {\n    auto values = containerInit();\n    values.grow_by_generator(kLength, [i = size_t{0}]() mutable { return i++; });\n  }\n}\n\nvoid BM_std_push_back_serial(benchmark::State& state) {\n  pushBackImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_push_back_serial(benchmark::State& state) {\n  pushBackImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_push_back_serial(benchmark::State& state) {\n  pushBackImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_push_back_serial(benchmark::State& state) {\n  pushBackImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_push_back_serial_grow_by_alternative(benchmark::State& state) {\n  pushBackGrowByAlternativeTbb(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_push_back_serial_grow_by_alternative(benchmark::State& state) {\n  pushBackGrowByAlternativeDispenso(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\nvoid BM_std_push_back_serial_reserve(benchmark::State& state) {\n  pushBackImpl(state, []() {\n    std::vector<int> v;\n    v.reserve(kLength);\n    return v;\n  });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_push_back_serial_reserve(benchmark::State& state) {\n  pushBackImpl(state, []() {\n    tbb::concurrent_vector<int> v;\n    v.reserve(kLength);\n    return v;\n  });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_push_back_serial_reserve(benchmark::State& state) {\n  pushBackImpl(\n      state, []() { return dispenso::ConcurrentVector<int>(kLength, dispenso::ReserveTag); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_push_back_serial_grow_by_alternative_reserve(benchmark::State& state) {\n  pushBackGrowByAlternativeTbb(state, []() {\n    tbb::concurrent_vector<int> v;\n    v.reserve(kLength);\n    return v;\n  });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_push_back_serial_grow_by_alternative_reserve(benchmark::State& state) {\n  pushBackGrowByAlternativeDispenso(\n      state, []() { return dispenso::ConcurrentVector<int>(kLength, dispenso::ReserveTag); });\n}\n\ntemplate <typename ContainerInit>\nvoid iterateImpl(benchmark::State& state, ContainerInit containerInit) {\n  auto values = containerInit();\n  for (size_t i = 0; i < kLength; ++i) {\n    values.push_back(i);\n  }\n  int64_t sum;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    for (auto i : values) {\n      sum += i;\n    }\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_iterate(benchmark::State& state) {\n  iterateImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_iterate(benchmark::State& state) {\n  iterateImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_iterate(benchmark::State& state) {\n  iterateImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_iterate(benchmark::State& state) {\n  iterateImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\ntemplate <typename T>\nstruct ReverseWrapper {\n  T& iterable;\n};\n\ntemplate <typename T>\nauto begin(ReverseWrapper<T> w) {\n  return std::rbegin(w.iterable);\n}\n\ntemplate <typename T>\nauto end(ReverseWrapper<T> w) {\n  return std::rend(w.iterable);\n}\n\ntemplate <typename T>\nReverseWrapper<T> reverse(T&& iterable) {\n  return {iterable};\n}\n\ntemplate <typename ContainerInit>\nvoid iterateReverseImpl(benchmark::State& state, ContainerInit containerInit) {\n  auto values = containerInit();\n  for (size_t i = 0; i < kLength; ++i) {\n    values.push_back(i);\n  }\n  int64_t sum;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    for (auto i : reverse(values)) {\n      sum += i;\n    }\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_iterate_reverse(benchmark::State& state) {\n  iterateReverseImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_iterate_reverse(benchmark::State& state) {\n  iterateReverseImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_iterate_reverse(benchmark::State& state) {\n  iterateReverseImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_iterate_reverse(benchmark::State& state) {\n  iterateReverseImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\ntemplate <typename ContainerInit>\nvoid lowerBoundImpl(benchmark::State& state, ContainerInit containerInit) {\n  auto values = containerInit();\n  for (size_t i = 0; i < kLength; ++i) {\n    values.push_back(i);\n  }\n  int64_t sum;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    for (size_t i = 0; i < kLength; ++i) {\n      sum += std::lower_bound(std::begin(values), std::end(values), i) - std::begin(values);\n    }\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_lower_bound(benchmark::State& state) {\n  lowerBoundImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_lower_bound(benchmark::State& state) {\n  lowerBoundImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_lower_bound(benchmark::State& state) {\n  lowerBoundImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_lower_bound(benchmark::State& state) {\n  lowerBoundImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\ntemplate <typename ContainerInit>\nvoid indexImpl(benchmark::State& state, ContainerInit containerInit) {\n  auto values = containerInit();\n  for (size_t i = 0; i < kLength; ++i) {\n    values.push_back(i);\n  }\n  int64_t sum;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    size_t len = values.size();\n    for (size_t i = 0; i < len; ++i) {\n      sum += values[i];\n    }\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_index(benchmark::State& state) {\n  indexImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_index(benchmark::State& state) {\n  indexImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_index(benchmark::State& state) {\n  indexImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_index(benchmark::State& state) {\n  indexImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\ntemplate <typename ContainerInit>\nvoid randomImpl(benchmark::State& state, ContainerInit containerInit) {\n  auto values = containerInit();\n  std::vector<size_t> indices;\n  for (size_t i = 0; i < kLength; ++i) {\n    values.push_back(i);\n    indices.push_back(i);\n  }\n\n  // Make this repeatable.\n  std::mt19937 rng(27);\n  std::shuffle(indices.begin(), indices.end(), rng);\n\n  int64_t sum;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    for (auto i : indices) {\n      sum += values[i];\n    }\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_random(benchmark::State& state) {\n  randomImpl(state, []() { return std::vector<int>(); });\n}\n\nvoid BM_deque_random(benchmark::State& state) {\n  randomImpl(state, []() { return std::deque<int>(); });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_random(benchmark::State& state) {\n  randomImpl(state, []() { return tbb::concurrent_vector<int>(); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_random(benchmark::State& state) {\n  randomImpl(state, []() { return dispenso::ConcurrentVector<int>(); });\n}\n\ntemplate <typename ContainerInit, typename ContainerPush>\nvoid parallelImpl(\n    benchmark::State& state,\n    ContainerInit containerInit,\n    ContainerPush containerPush) {\n  for (auto UNUSED_VAR : state) {\n    auto values = containerInit();\n    dispenso::parallel_for(\n        0, kLength, [&values, containerPush](size_t i) { containerPush(values, i); });\n  }\n}\n\nvoid BM_std_parallel(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImpl(\n      state,\n      []() { return std::vector<int>(); },\n      [&mtx](std::vector<int>& c, int i) {\n        std::lock_guard<std::mutex> lk(mtx);\n        c.push_back(i);\n      });\n}\n\nvoid BM_deque_parallel(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImpl(\n      state,\n      []() { return std::deque<int>(); },\n      [&mtx](std::deque<int>& c, int i) {\n        std::lock_guard<std::mutex> lk(mtx);\n        c.push_back(i);\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel(benchmark::State& state) {\n  parallelImpl(\n      state,\n      []() { return tbb::concurrent_vector<int>(); },\n      [](tbb::concurrent_vector<int>& c, int i) { c.push_back(i); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel(benchmark::State& state) {\n  parallelImpl(\n      state,\n      []() { return dispenso::ConcurrentVector<int>(); },\n      [](dispenso::ConcurrentVector<int>& c, int i) { c.push_back(i); });\n}\n\nvoid BM_std_parallel_reserve(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImpl(\n      state,\n      []() {\n        std::vector<int> v;\n        v.reserve(kLength);\n        return v;\n      },\n      [&mtx](std::vector<int>& c, int i) {\n        std::lock_guard<std::mutex> lk(mtx);\n        c.push_back(i);\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel_reserve(benchmark::State& state) {\n  parallelImpl(\n      state,\n      []() {\n        tbb::concurrent_vector<int> v;\n        v.reserve(kLength);\n        return v;\n      },\n      [](tbb::concurrent_vector<int>& c, int i) { c.push_back(i); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel_reserve(benchmark::State& state) {\n  parallelImpl(\n      state,\n      []() { return dispenso::ConcurrentVector<int>(kLength, dispenso::ReserveTag); },\n      [](dispenso::ConcurrentVector<int>& c, int i) { c.push_back(i); });\n}\n\ntemplate <typename ContainerInit, typename ContainerPush>\nvoid parallelImplClear(\n    benchmark::State& state,\n    ContainerInit containerInit,\n    ContainerPush containerPush) {\n  auto values = containerInit();\n\n  for (auto UNUSED_VAR : state) {\n    values.clear();\n    dispenso::parallel_for(\n        0, kLength, [&values, containerPush](size_t i) { containerPush(values, i); });\n  }\n\n  int64_t sum = 0;\n\n  for (auto i : values) {\n    sum += i;\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_parallel_clear(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplClear(\n      state,\n      []() { return std::vector<int>(); },\n      [&mtx](std::vector<int>& c, int i) {\n        std::lock_guard<std::mutex> lk(mtx);\n        c.push_back(i);\n      });\n}\n\nvoid BM_deque_parallel_clear(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplClear(\n      state,\n      []() { return std::deque<int>(); },\n      [&mtx](std::deque<int>& c, int i) {\n        std::lock_guard<std::mutex> lk(mtx);\n        c.push_back(i);\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel_clear(benchmark::State& state) {\n  parallelImplClear(\n      state,\n      []() { return tbb::concurrent_vector<int>(); },\n      [](tbb::concurrent_vector<int>& c, int i) { c.push_back(i); });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel_clear(benchmark::State& state) {\n  parallelImplClear(\n      state,\n      []() { return dispenso::ConcurrentVector<int>(); },\n      [](dispenso::ConcurrentVector<int>& c, int i) { c.push_back(i); });\n}\n\ntemplate <typename ContainerInit, typename ContainerPush>\nvoid parallelImplGrowBy(\n    size_t growBy,\n    benchmark::State& state,\n    ContainerInit containerInit,\n    ContainerPush containerPush) {\n  auto values = containerInit();\n\n  for (auto UNUSED_VAR : state) {\n    values.clear();\n    dispenso::parallel_for(\n        dispenso::makeChunkedRange(0, kLength, dispenso::ParForChunking::kStatic),\n        [&values, containerPush, growBy](size_t i, size_t end) {\n          while (i + growBy <= end) {\n            containerPush(values, i, i + growBy);\n            i += growBy;\n          }\n          containerPush(values, i, end);\n        });\n  }\n\n  int64_t sum = 0;\n\n  for (auto i : values) {\n    sum += i;\n  }\n\n  checkIotaSum(values, sum);\n}\n\nvoid BM_std_parallel_grow_by_10(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowBy(\n      10,\n      state,\n      []() { return std::vector<int>(); },\n      [&mtx](std::vector<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\nvoid BM_deque_parallel_grow_by_10(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowBy(\n      10,\n      state,\n      []() { return std::deque<int>(); },\n      [&mtx](std::deque<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel_grow_by_10(benchmark::State& state) {\n  parallelImplGrowBy(\n      10,\n      state,\n      []() { return tbb::concurrent_vector<int>(); },\n      [](tbb::concurrent_vector<int>& c, int i, int end) {\n        auto it = c.grow_by(end - i);\n        for (; i != end; ++i, ++it) {\n          *it = i;\n        }\n      });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel_grow_by_10(benchmark::State& state) {\n  parallelImplGrowBy(\n      10,\n      state,\n      []() { return dispenso::ConcurrentVector<int>(); },\n      [](dispenso::ConcurrentVector<int>& c, int i, int end) {\n        c.grow_by_generator(end - i, [i]() mutable { return i++; });\n      });\n}\n\nvoid BM_std_parallel_grow_by_100(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowBy(\n      100,\n      state,\n      []() { return std::vector<int>(); },\n      [&mtx](std::vector<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\nvoid BM_deque_parallel_grow_by_100(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowBy(\n      100,\n      state,\n      []() { return std::deque<int>(); },\n      [&mtx](std::deque<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel_grow_by_100(benchmark::State& state) {\n  parallelImplGrowBy(\n      100,\n      state,\n      []() { return tbb::concurrent_vector<int>(); },\n      [](tbb::concurrent_vector<int>& c, int i, int end) {\n        auto it = c.grow_by(end - i);\n        for (; i != end; ++i, ++it) {\n          *it = i;\n        }\n      });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel_grow_by_100(benchmark::State& state) {\n  parallelImplGrowBy(\n      100,\n      state,\n      []() { return dispenso::ConcurrentVector<int>(); },\n      [](dispenso::ConcurrentVector<int>& c, int i, int end) {\n        c.grow_by_generator(end - i, [i]() mutable { return i++; });\n      });\n}\n\ntemplate <typename ContainerInit, typename ContainerPush>\nvoid parallelImplGrowByMax(\n    benchmark::State& state,\n    ContainerInit containerInit,\n    ContainerPush containerPush) {\n  auto values = containerInit();\n\n  for (auto UNUSED_VAR : state) {\n    values.clear();\n    dispenso::parallel_for(\n        dispenso::makeChunkedRange(0, kLength, dispenso::ParForChunking::kStatic),\n        [&values, containerPush](size_t i, size_t end) { containerPush(values, i, end); });\n  }\n\n  int64_t sum = 0;\n\n  for (auto i : values) {\n    sum += i;\n  }\n\n  checkIotaSum(sum);\n}\n\nvoid BM_std_parallel_grow_by_max(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowByMax(\n      state,\n      []() { return std::vector<int>(); },\n      [&mtx](std::vector<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\nvoid BM_deque_parallel_grow_by_max(benchmark::State& state) {\n  std::mutex mtx;\n  parallelImplGrowByMax(\n      state,\n      []() { return std::deque<int>(); },\n      [&mtx](std::deque<int>& c, int i, int end) {\n        std::lock_guard<std::mutex> lk(mtx);\n        for (; i != end; ++i) {\n          c.push_back(i);\n        }\n      });\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_parallel_grow_by_max(benchmark::State& state) {\n  parallelImplGrowByMax(\n      state,\n      []() { return tbb::concurrent_vector<int>(); },\n      [](tbb::concurrent_vector<int>& c, int i, int end) {\n        auto it = c.grow_by(end - i);\n        for (; i != end; ++i, ++it) {\n          *it = i;\n        }\n      });\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_parallel_grow_by_max(benchmark::State& state) {\n  parallelImplGrowByMax(\n      state,\n      []() { return dispenso::ConcurrentVector<int>(); },\n      [](dispenso::ConcurrentVector<int>& c, int i, int end) {\n        c.grow_by_generator(end - i, [i]() mutable { return i++; });\n      });\n}\n\nBENCHMARK(BM_std_push_back_serial);\nBENCHMARK(BM_deque_push_back_serial);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_push_back_serial);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_push_back_serial);\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_push_back_serial_grow_by_alternative);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_push_back_serial_grow_by_alternative);\n\nBENCHMARK(BM_std_push_back_serial_reserve);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_push_back_serial_reserve);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_push_back_serial_reserve);\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_push_back_serial_grow_by_alternative_reserve);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_push_back_serial_grow_by_alternative_reserve);\n\nBENCHMARK(BM_std_iterate);\nBENCHMARK(BM_deque_iterate);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_iterate);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_iterate);\n\nBENCHMARK(BM_std_iterate_reverse);\nBENCHMARK(BM_deque_iterate_reverse);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_iterate_reverse);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_iterate_reverse);\n\nBENCHMARK(BM_std_lower_bound);\nBENCHMARK(BM_deque_lower_bound);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_lower_bound);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_lower_bound);\n\nBENCHMARK(BM_std_index);\nBENCHMARK(BM_deque_index);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_index);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_index);\n\nBENCHMARK(BM_std_random);\nBENCHMARK(BM_deque_random);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_random);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_random);\n\nBENCHMARK(BM_std_parallel);\nBENCHMARK(BM_deque_parallel);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel);\n\nBENCHMARK(BM_std_parallel_reserve);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel_reserve);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel_reserve);\n\nBENCHMARK(BM_std_parallel_clear);\nBENCHMARK(BM_deque_parallel_clear);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel_clear);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel_clear);\n\nBENCHMARK(BM_std_parallel_grow_by_10);\nBENCHMARK(BM_deque_parallel_grow_by_10);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel_grow_by_10);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel_grow_by_10);\n\nBENCHMARK(BM_std_parallel_grow_by_100);\nBENCHMARK(BM_deque_parallel_grow_by_100);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel_grow_by_100);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel_grow_by_100);\n\nBENCHMARK(BM_std_parallel_grow_by_max);\nBENCHMARK(BM_deque_parallel_grow_by_max);\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_parallel_grow_by_max);\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_parallel_grow_by_max);\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/fast_math/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.12)\n\n# Apply SIMD ISA flags and Highway linkage from parent.\nset(FAST_MATH_EXTRA_FLAGS ${DISPENSO_FAST_MATH_SIMD_FLAGS})\nset(FAST_MATH_EXTRA_LIBS \"\")\nif(DISPENSO_FAST_MATH_HIGHWAY AND TARGET hwy)\n  list(APPEND FAST_MATH_EXTRA_LIBS hwy)\n  # Treat Highway as a system include to suppress warnings from its headers.\n  if(MSVC)\n    list(APPEND FAST_MATH_EXTRA_FLAGS /external:I ${hwy_SOURCE_DIR})\n  else()\n    list(APPEND FAST_MATH_EXTRA_FLAGS -isystem${hwy_SOURCE_DIR})\n  endif()\nendif()\n\nfile(GLOB FAST_MATH_BENCHMARK_FILES CONFIGURE_DEPENDS *.cpp)\n\nforeach(BENCHMARK_FILE ${FAST_MATH_BENCHMARK_FILES})\n  set(BENCHMARK_NAME)\n  get_filename_component(BENCHMARK_NAME ${BENCHMARK_FILE} NAME_WE)\n  set(BENCHMARK_NAME \"fast_math_${BENCHMARK_NAME}\")\n  add_executable(${BENCHMARK_NAME} ${BENCHMARK_FILE})\n  target_compile_features(${BENCHMARK_NAME} PRIVATE cxx_std_17)\n  target_compile_options(${BENCHMARK_NAME} PRIVATE ${FAST_MATH_EXTRA_FLAGS})\n  target_link_libraries(${BENCHMARK_NAME} ${REQUIRED_LIBS} ${OPTIONAL_LIBS} ${FAST_MATH_EXTRA_LIBS})\nendforeach()\n"
  },
  {
    "path": "benchmarks/fast_math/avx512_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\n#if defined(__AVX512F__)\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\nusing Flt = __m512;\n\n// --- One-arg benchmarks ---\n\nvoid BM_sin_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_cos_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_tan_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_atan_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_acos_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_asin_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::asin(x); });\n}\n\nvoid BM_exp_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_exp2_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_exp10_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_expm1_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::expm1(x); });\n}\n\nvoid BM_log_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_log2_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_log10_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_log1p_avx512(benchmark::State& state) {\n  bench::runBench(\n      state, bench::sinInputs<Flt>(), [](Flt x) { return dfm::log1p(_mm512_abs_ps(x)); });\n}\n\nvoid BM_cbrt_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::cbrt(x); });\n}\n\nvoid BM_frexp_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    dfm::IntType_t<Flt> e;\n    return dfm::frexp(x, &e);\n  });\n}\nvoid BM_ldexp_avx512(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return dfm::ldexp(x, _mm512_set1_epi32(3)); });\n}\n\nvoid BM_tanh_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::tanhInputs<Flt>(), [](auto x) { return dfm::tanh(x); });\n}\nvoid BM_erf_avx512(benchmark::State& state) {\n  bench::runBench(state, bench::erfInputs<Flt>(), [](auto x) { return dfm::erf(x); });\n}\n\n// --- Two-arg benchmarks ---\n\nvoid BM_atan2_avx512(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return dfm::atan2(y, x);\n  });\n}\n\nvoid BM_hypot_avx512(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot(x, y);\n  });\n}\nvoid BM_hypot_avx512_bounds(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\n\nvoid BM_pow_avx512(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow(b, e);\n      });\n}\nvoid BM_pow_avx512_accurate(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow<Flt, dfm::MaxAccuracyTraits>(b, e);\n      });\n}\nvoid BM_pow_avx512_scalar_exp(benchmark::State& state) {\n  bench::runBench(state, bench::powBaseInputs<Flt>(), [](auto x) { return dfm::pow(x, 2.5f); });\n}\n\n// --- Libc-packed comparisons (AVX-512-specific, kept hand-written) ---\n\nvoid BM_hypot_libc_avx512(benchmark::State& state) {\n  const auto& inputs = bench::hypotInputs<Flt>();\n  const auto& inputs2 = bench::sinInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = _mm512_setzero_ps();\n  for (auto _ : state) {\n    (void)_;\n    alignas(64) float x[16], y[16], r[16];\n    _mm512_store_ps(x, inputs[idx]);\n    _mm512_store_ps(y, inputs2[idx]);\n    for (int32_t i = 0; i < 16; ++i) {\n      r[i] = ::hypotf(x[i], y[i]);\n    }\n    sum = _mm512_add_ps(sum, _mm512_load_ps(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 16);\n  bench::consumeResult(sum);\n}\n\nvoid BM_pow_libc_avx512(benchmark::State& state) {\n  const auto& bases = bench::powBaseInputs<Flt>();\n  const auto& exps = bench::powExpInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = _mm512_setzero_ps();\n  for (auto _ : state) {\n    (void)_;\n    alignas(64) float x[16], y[16], r[16];\n    _mm512_store_ps(x, bases[idx]);\n    _mm512_store_ps(y, exps[idx]);\n    for (int32_t j = 0; j < 16; ++j)\n      r[j] = ::powf(x[j], y[j]);\n    sum = _mm512_add_ps(sum, _mm512_load_ps(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 16);\n  bench::consumeResult(sum);\n}\n\n// --- Registrations ---\n\nBENCHMARK(BM_sin_avx512);\nBENCHMARK(BM_cos_avx512);\nBENCHMARK(BM_tan_avx512);\nBENCHMARK(BM_atan_avx512);\nBENCHMARK(BM_acos_avx512);\nBENCHMARK(BM_asin_avx512);\nBENCHMARK(BM_exp_avx512);\nBENCHMARK(BM_exp2_avx512);\nBENCHMARK(BM_exp10_avx512);\nBENCHMARK(BM_expm1_avx512);\nBENCHMARK(BM_log_avx512);\nBENCHMARK(BM_log2_avx512);\nBENCHMARK(BM_log10_avx512);\nBENCHMARK(BM_log1p_avx512);\nBENCHMARK(BM_cbrt_avx512);\nBENCHMARK(BM_frexp_avx512);\nBENCHMARK(BM_ldexp_avx512);\nBENCHMARK(BM_tanh_avx512);\nBENCHMARK(BM_erf_avx512);\nBENCHMARK(BM_atan2_avx512);\nBENCHMARK(BM_hypot_avx512);\nBENCHMARK(BM_hypot_avx512_bounds);\nBENCHMARK(BM_hypot_libc_avx512);\nBENCHMARK(BM_pow_avx512);\nBENCHMARK(BM_pow_avx512_accurate);\nBENCHMARK(BM_pow_avx512_scalar_exp);\nBENCHMARK(BM_pow_libc_avx512);\n\n#else // !defined(__AVX512F__)\n\nint main() {\n  std::cout << \"AVX-512 not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // defined(__AVX512F__)\n"
  },
  {
    "path": "benchmarks/fast_math/avx_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\n#if defined(__AVX2__)\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\nusing Flt = __m256;\n\nstruct BoundsTraits {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;\n};\n\n// --- One-arg benchmarks ---\n\nvoid BM_sin_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_sin_avx_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::sin<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_cos_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_cos_avx_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::cos<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_tan_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_atan_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_acos_avx(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_asin_avx(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::asin(x); });\n}\n\nvoid BM_exp_avx(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_exp_avx_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) {\n    return dfm::exp<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_exp_avx_bounds(benchmark::State& state) {\n  bench::runBench(\n      state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp<Flt, BoundsTraits>(x); });\n}\nvoid BM_exp2_avx(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_exp10_avx(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_expm1_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::expm1(x); });\n}\n\nvoid BM_log_avx(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_log_avx_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::log<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_log2_avx(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_log10_avx(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_log1p_avx(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](Flt x) {\n    Flt ax = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), x);\n    return dfm::log1p(ax);\n  });\n}\n\nvoid BM_cbrt_avx(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::cbrt(x); });\n}\nvoid BM_cbrt_avx_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::cbrt<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\n\nvoid BM_frexp_avx(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    dfm::IntType_t<Flt> e;\n    return dfm::frexp(x, &e);\n  });\n}\nvoid BM_ldexp_avx(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return dfm::ldexp(x, _mm256_set1_epi32(3)); });\n}\n\nvoid BM_tanh_avx(benchmark::State& state) {\n  bench::runBench(state, bench::tanhInputs<Flt>(), [](auto x) { return dfm::tanh(x); });\n}\nvoid BM_erf_avx(benchmark::State& state) {\n  bench::runBench(state, bench::erfInputs<Flt>(), [](auto x) { return dfm::erf(x); });\n}\n\n// --- Two-arg benchmarks ---\n\nvoid BM_atan2_avx(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return dfm::atan2(y, x);\n  });\n}\n\nvoid BM_hypot_avx(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot(x, y);\n  });\n}\nvoid BM_hypot_avx_bounds(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\n\nvoid BM_pow_avx(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow(b, e);\n      });\n}\nvoid BM_pow_avx_accurate(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow<Flt, dfm::MaxAccuracyTraits>(b, e);\n      });\n}\nvoid BM_pow_avx_scalar_exp(benchmark::State& state) {\n  bench::runBench(state, bench::powBaseInputs<Flt>(), [](auto x) { return dfm::pow(x, 2.5f); });\n}\n\n// --- Libc-packed comparison (AVX-specific, kept hand-written) ---\n\nvoid BM_pow_libc_avx(benchmark::State& state) {\n  const auto& bases = bench::powBaseInputs<Flt>();\n  const auto& exps = bench::powExpInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = _mm256_setzero_ps();\n  for (auto _ : state) {\n    (void)_;\n    alignas(32) float x[8], y[8], r[8];\n    _mm256_store_ps(x, bases[idx]);\n    _mm256_store_ps(y, exps[idx]);\n    for (int32_t i = 0; i < 8; ++i) {\n      r[i] = ::powf(x[i], y[i]);\n    }\n    sum = _mm256_add_ps(sum, _mm256_load_ps(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 8);\n  bench::consumeResult(sum);\n}\n\n// --- Registrations ---\n\nBENCHMARK(BM_sin_avx);\nBENCHMARK(BM_sin_avx_accurate);\nBENCHMARK(BM_cos_avx);\nBENCHMARK(BM_cos_avx_accurate);\nBENCHMARK(BM_tan_avx);\nBENCHMARK(BM_atan_avx);\nBENCHMARK(BM_acos_avx);\nBENCHMARK(BM_asin_avx);\nBENCHMARK(BM_exp_avx);\nBENCHMARK(BM_exp_avx_accurate);\nBENCHMARK(BM_exp_avx_bounds);\nBENCHMARK(BM_exp2_avx);\nBENCHMARK(BM_exp10_avx);\nBENCHMARK(BM_expm1_avx);\nBENCHMARK(BM_log_avx);\nBENCHMARK(BM_log_avx_accurate);\nBENCHMARK(BM_log2_avx);\nBENCHMARK(BM_log10_avx);\nBENCHMARK(BM_log1p_avx);\nBENCHMARK(BM_cbrt_avx);\nBENCHMARK(BM_cbrt_avx_accurate);\nBENCHMARK(BM_frexp_avx);\nBENCHMARK(BM_ldexp_avx);\nBENCHMARK(BM_tanh_avx);\nBENCHMARK(BM_erf_avx);\nBENCHMARK(BM_atan2_avx);\nBENCHMARK(BM_hypot_avx);\nBENCHMARK(BM_hypot_avx_bounds);\nBENCHMARK(BM_pow_avx);\nBENCHMARK(BM_pow_avx_accurate);\nBENCHMARK(BM_pow_avx_scalar_exp);\nBENCHMARK(BM_pow_libc_avx);\n\n#else // !defined(__AVX2__)\n\nint main() {\n  std::cout << \"AVX2 not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // defined(__AVX2__)\n"
  },
  {
    "path": "benchmarks/fast_math/benchmark_helpers.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <cmath>\n#include <cstdint>\n#include <iostream>\n#include <vector>\n\n#include <benchmark/benchmark.h>\n#include <dispenso/fast_math/fast_math.h>\n\n#if __has_include(\"hwy/highway.h\")\n#include \"hwy/highway.h\"\n#endif\n\nnamespace dispenso {\nnamespace fast_math {\nnamespace bench {\n\nconstexpr size_t kNumInputs = 4096;\nconstexpr size_t kInputsMask = 4095;\nconstexpr int32_t kMaxBenchLanes = 64;\n\n// --- Per-type primitives ---\n//\n// Each SIMD type needs: laneCount, loadVec, zeroVec, addVec, consumeResult.\n// These are template specializations so the compiler sees the exact operations\n// at each call site, ensuring zero overhead.\n\ntemplate <typename Flt>\ninline int32_t laneCount();\ntemplate <typename Flt>\ninline Flt loadVec(const float* data);\ntemplate <typename Flt>\ninline Flt zeroVec();\ntemplate <typename Flt>\ninline Flt addVec(Flt a, Flt b);\ntemplate <typename Flt>\ninline void consumeResult(Flt sum);\n\n// --- Scalar (float) ---\n\ntemplate <>\ninline int32_t laneCount<float>() {\n  return 1;\n}\ntemplate <>\ninline float loadVec<float>(const float* data) {\n  return *data;\n}\ntemplate <>\ninline float zeroVec<float>() {\n  return 0.0f;\n}\ntemplate <>\ninline float addVec<float>(float a, float b) {\n  return a + b;\n}\ntemplate <>\ninline void consumeResult<float>(float sum) {\n  std::cout << sum << std::endl;\n}\n\n// --- SSE (__m128) ---\n\n#if defined(__SSE4_1__)\n\ntemplate <>\ninline int32_t laneCount<__m128>() {\n  return 4;\n}\ntemplate <>\ninline __m128 loadVec<__m128>(const float* data) {\n  return _mm_load_ps(data);\n}\ntemplate <>\ninline __m128 zeroVec<__m128>() {\n  return _mm_setzero_ps();\n}\ntemplate <>\ninline __m128 addVec<__m128>(__m128 a, __m128 b) {\n  return _mm_add_ps(a, b);\n}\ntemplate <>\ninline void consumeResult<__m128>(__m128 sum) {\n  alignas(16) float buf[4];\n  _mm_store_ps(buf, sum);\n  std::cout << buf[0] + buf[1] + buf[2] + buf[3] << std::endl;\n}\n\n#endif // __SSE4_1__\n\n// --- AVX (__m256) ---\n\n#if defined(__AVX2__)\n\ntemplate <>\ninline int32_t laneCount<__m256>() {\n  return 8;\n}\ntemplate <>\ninline __m256 loadVec<__m256>(const float* data) {\n  return _mm256_load_ps(data);\n}\ntemplate <>\ninline __m256 zeroVec<__m256>() {\n  return _mm256_setzero_ps();\n}\ntemplate <>\ninline __m256 addVec<__m256>(__m256 a, __m256 b) {\n  return _mm256_add_ps(a, b);\n}\ntemplate <>\ninline void consumeResult<__m256>(__m256 sum) {\n  alignas(32) float buf[8];\n  _mm256_store_ps(buf, sum);\n  float total = 0.0f;\n  for (int32_t i = 0; i < 8; ++i)\n    total += buf[i];\n  std::cout << total << std::endl;\n}\n\n#endif // __AVX2__\n\n// --- AVX-512 (__m512) ---\n\n#if defined(__AVX512F__)\n\ntemplate <>\ninline int32_t laneCount<__m512>() {\n  return 16;\n}\ntemplate <>\ninline __m512 loadVec<__m512>(const float* data) {\n  return _mm512_load_ps(data);\n}\ntemplate <>\ninline __m512 zeroVec<__m512>() {\n  return _mm512_setzero_ps();\n}\ntemplate <>\ninline __m512 addVec<__m512>(__m512 a, __m512 b) {\n  return _mm512_add_ps(a, b);\n}\ntemplate <>\ninline void consumeResult<__m512>(__m512 sum) {\n  alignas(64) float buf[16];\n  _mm512_store_ps(buf, sum);\n  float total = 0.0f;\n  for (int32_t i = 0; i < 16; ++i)\n    total += buf[i];\n  std::cout << total << std::endl;\n}\n\n#endif // __AVX512F__\n\n// --- NEON (float32x4_t) ---\n\n#if defined(__aarch64__)\n\ntemplate <>\ninline int32_t laneCount<float32x4_t>() {\n  return 4;\n}\ntemplate <>\ninline float32x4_t loadVec<float32x4_t>(const float* data) {\n  return vld1q_f32(data);\n}\ntemplate <>\ninline float32x4_t zeroVec<float32x4_t>() {\n  return vdupq_n_f32(0.0f);\n}\ntemplate <>\ninline float32x4_t addVec<float32x4_t>(float32x4_t a, float32x4_t b) {\n  return vaddq_f32(a, b);\n}\ntemplate <>\ninline void consumeResult<float32x4_t>(float32x4_t sum) {\n  alignas(16) float buf[4];\n  vst1q_f32(buf, sum);\n  std::cout << buf[0] + buf[1] + buf[2] + buf[3] << std::endl;\n}\n\n#endif // __aarch64__\n\n// --- Highway (HwyFloat) ---\n\n#if __has_include(\"hwy/highway.h\")\n\nnamespace hn = hwy::HWY_NAMESPACE;\n\ntemplate <>\ninline int32_t laneCount<HwyFloat>() {\n  return static_cast<int32_t>(hn::Lanes(HwyFloatTag()));\n}\ntemplate <>\ninline HwyFloat loadVec<HwyFloat>(const float* data) {\n  return hn::LoadU(HwyFloatTag(), data);\n}\ntemplate <>\ninline HwyFloat zeroVec<HwyFloat>() {\n  return hn::Zero(HwyFloatTag());\n}\ntemplate <>\ninline HwyFloat addVec<HwyFloat>(HwyFloat a, HwyFloat b) {\n  return hn::Add(a.v, b.v);\n}\ntemplate <>\ninline void consumeResult<HwyFloat>(HwyFloat sum) {\n  const HwyFloatTag d;\n  constexpr size_t kMaxLanes = HWY_MAX_BYTES / sizeof(float);\n  HWY_ALIGN float buf[kMaxLanes];\n  hn::StoreU(sum.v, d, buf);\n  float total = 0.0f;\n  const size_t N = hn::Lanes(d);\n  for (size_t i = 0; i < N; ++i) {\n    total += buf[i];\n  }\n  std::cout << total << std::endl;\n}\n\n#endif // hwy/highway.h\n\n// --- Input generation ---\n//\n// makeInputs<Flt>(lo, hi) generates kNumInputs vectors covering the scalar\n// range [lo, hi] at delta = (hi - lo) / kNumInputs spacing. Each SIMD vector\n// packs N consecutive values, so the total coverage is N * (hi - lo).\n\ntemplate <typename Flt>\ninline std::vector<Flt> makeInputs(float lo, float hi) {\n  const int32_t N = laneCount<Flt>();\n  float delta = (hi - lo) / static_cast<float>(kNumInputs);\n  std::vector<Flt> inputs;\n  inputs.reserve(kNumInputs);\n  alignas(64) float buf[kMaxBenchLanes];\n  float f = lo;\n  for (size_t i = 0; i < kNumInputs; ++i) {\n    for (int32_t j = 0; j < N; ++j) {\n      buf[j] = f + static_cast<float>(j) * delta;\n    }\n    inputs.push_back(loadVec<Flt>(buf));\n    f += static_cast<float>(N) * delta;\n  }\n  return inputs;\n}\n\n// --- Pre-defined input factories ---\n//\n// These match the ranges used across all SIMD benchmark files.\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& sinInputs() {\n  static auto v = makeInputs<Flt>(static_cast<float>(-M_PI / 2.0), static_cast<float>(M_PI / 2.0));\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& expInputs() {\n  static auto v = makeInputs<Flt>(-10.0f, 10.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& logInputs() {\n  static auto v = makeInputs<Flt>(0.001f, 10000.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& acosInputs() {\n  static auto v = makeInputs<Flt>(-0.999f, 0.999f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& hypotInputs() {\n  static auto v = makeInputs<Flt>(-100000.0f, 100000.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& tanhInputs() {\n  static auto v = makeInputs<Flt>(-5.0f, 5.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& erfInputs() {\n  static auto v = makeInputs<Flt>(-4.0f, 4.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& powBaseInputs() {\n  static auto v = makeInputs<Flt>(0.01f, 100.0f);\n  return v;\n}\n\ntemplate <typename Flt>\ninline const std::vector<Flt>& powExpInputs() {\n  static auto v = makeInputs<Flt>(-8.0f, 8.0f);\n  return v;\n}\n\n// --- Benchmark runners ---\n//\n// runBench: one-arg function benchmark. Func is a template parameter (lambda),\n// so the compiler sees the exact call target and inlines at -O2. This produces\n// the same assembly as hand-written code.\n//\n// runBench2: two-arg function benchmark (atan2, hypot, pow).\n\ntemplate <typename Flt, typename Func>\ninline void runBench(benchmark::State& state, const std::vector<Flt>& inputs, Func fn) {\n  size_t idx = 0;\n  Flt sum = zeroVec<Flt>();\n  for (auto _ : state) {\n    (void)_;\n    sum = addVec<Flt>(sum, fn(inputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(laneCount<Flt>()));\n  consumeResult(sum);\n}\n\ntemplate <typename Flt, typename Func>\ninline void runBench2(\n    benchmark::State& state,\n    const std::vector<Flt>& xInputs,\n    const std::vector<Flt>& yInputs,\n    Func fn) {\n  size_t idx = 0;\n  Flt sum = zeroVec<Flt>();\n  for (auto _ : state) {\n    (void)_;\n    sum = addVec<Flt>(sum, fn(xInputs[idx], yInputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(laneCount<Flt>()));\n  consumeResult(sum);\n}\n\n} // namespace bench\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "benchmarks/fast_math/benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\n\nconstexpr size_t kNumInputs = 4096;\nconstexpr size_t kInputsMask = 4095;\n\nstruct BoundsTraits {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;\n};\n\n// --- Input generators (scalar-specific ranges, different from SIMD) ---\n\nconst std::vector<float>& acosInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 2.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -1.0f; f <= 1.0f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& cbrtInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 50000.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -50000.f; f <= 50000.f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& sinInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = M_PI / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -M_PI / 2.0; f <= M_PI / 2.0; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& logInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 10000.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = 0.0f; f <= 10000.0f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& hypotInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 200000.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -100000.f; f <= 100000.f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& powBaseInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 99.99f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = 0.01f; f <= 100.0f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& powExpInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 16.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -8.0f; f <= 8.0f; f += delta) {\n      inp.push_back(f);\n    }\n    while (inp.size() < kNumInputs) {\n      inp.push_back(inp.back());\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<float>& tanhInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 10.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -5.0f; inp.size() < kNumInputs; f += delta) {\n      inp.push_back(f);\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\n// --- Libc benchmarks ---\n\nvoid BM_acos(benchmark::State& state) {\n  bench::runBench(state, acosInputs(), [](auto x) { return ::acosf(x); });\n}\nvoid BM_asin(benchmark::State& state) {\n  bench::runBench(state, acosInputs(), [](auto x) { return ::asinf(x); });\n}\nvoid BM_atan(benchmark::State& state) {\n  bench::runBench(state, cbrtInputs(), [](auto x) { return ::atanf(x); });\n}\nvoid BM_cbrt(benchmark::State& state) {\n  bench::runBench(state, cbrtInputs(), [](auto x) { return ::cbrtf(x); });\n}\nvoid BM_sin(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::sinf(x); });\n}\nvoid BM_cos(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::cosf(x); });\n}\nvoid BM_tan(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::tanf(x); });\n}\nvoid BM_exp(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::expf(x); });\n}\nvoid BM_exp2(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::exp2f(x); });\n}\nvoid BM_exp10(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::powf(10.0f, x); });\n}\nvoid BM_log(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return ::logf(x); });\n}\nvoid BM_log2(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return ::log2f(x); });\n}\nvoid BM_log10(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return ::log10f(x); });\n}\nvoid BM_expm1(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::expm1f(x); });\n}\nvoid BM_log1p(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::log1pf(std::fabs(x)); });\n}\nvoid BM_tanh(benchmark::State& state) {\n  bench::runBench(state, tanhInputs(), [](auto x) { return ::tanhf(x); });\n}\nvoid BM_sin_plus_cos(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return ::sinf(x) + ::cosf(x); });\n}\n\nvoid BM_atan2(benchmark::State& state) {\n  bench::runBench2(state, cbrtInputs(), sinInputs(), [](auto y, auto x) { return ::atan2f(y, x); });\n}\nvoid BM_hypot(benchmark::State& state) {\n  bench::runBench2(\n      state, hypotInputs(), sinInputs(), [](auto x, auto y) { return ::hypotf(x, y); });\n}\nvoid BM_pow(benchmark::State& state) {\n  bench::runBench2(\n      state, powBaseInputs(), powExpInputs(), [](auto b, auto e) { return ::powf(b, e); });\n}\n\n// frexp and ldexp use non-standard loop patterns — kept hand-written.\nvoid BM_frexp(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  int exp;\n  int64_t expSum = 0;\n  for (auto _ : state) {\n    (void)_;\n    sum += ::frexpf(inputs[idx], &exp);\n    expSum += exp;\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << \" \" << expSum << std::endl;\n}\n\nvoid BM_ldexp(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  for (auto _ : state) {\n    (void)_;\n    sum += ::ldexpf(inputs[idx], idx & 7);\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << std::endl;\n}\n\n// --- Dispenso fast_math benchmarks ---\n\nvoid BM_fastm_acos(benchmark::State& state) {\n  bench::runBench(state, acosInputs(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_fastm_asin(benchmark::State& state) {\n  bench::runBench(state, acosInputs(), [](auto x) { return dfm::asin(x); });\n}\nvoid BM_fastm_atan(benchmark::State& state) {\n  bench::runBench(state, cbrtInputs(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_fastm_cbrt(benchmark::State& state) {\n  bench::runBench(state, cbrtInputs(), [](auto x) { return dfm::cbrt(x); });\n}\nvoid BM_fastm_cbrt_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, cbrtInputs(), [](auto x) { return dfm::cbrt<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_sin(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_fastm_sin_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::sin<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_cos(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_fastm_cos_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::cos<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_tan(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_fastm_tan_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::tan<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_exp(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_fastm_exp_bounds(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::exp<float, BoundsTraits>(x); });\n}\nvoid BM_fastm_exp_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::exp<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_exp2(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_fastm_exp2_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::exp2<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_exp10(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_fastm_exp10_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, sinInputs(), [](auto x) { return dfm::exp10<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_log(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_fastm_log_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, logInputs(), [](auto x) { return dfm::log<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_log2(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_fastm_log2_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, logInputs(), [](auto x) { return dfm::log2<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_log10(benchmark::State& state) {\n  bench::runBench(state, logInputs(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_fastm_log10_accurate(benchmark::State& state) {\n  bench::runBench(\n      state, logInputs(), [](auto x) { return dfm::log10<float, dfm::MaxAccuracyTraits>(x); });\n}\nvoid BM_fastm_expm1(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::expm1(x); });\n}\nvoid BM_fastm_log1p(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::log1p(std::fabs(x)); });\n}\nvoid BM_fastm_tanh(benchmark::State& state) {\n  bench::runBench(state, tanhInputs(), [](auto x) { return dfm::tanh(x); });\n}\n\nvoid BM_fastm_atan2(benchmark::State& state) {\n  bench::runBench2(\n      state, cbrtInputs(), sinInputs(), [](auto y, auto x) { return dfm::atan2(y, x); });\n}\nvoid BM_fastm_atan2_bounds(benchmark::State& state) {\n  bench::runBench2(state, cbrtInputs(), sinInputs(), [](auto y, auto x) {\n    return dfm::atan2<float, BoundsTraits>(y, x);\n  });\n}\nvoid BM_fastm_hypot(benchmark::State& state) {\n  bench::runBench2(\n      state, hypotInputs(), sinInputs(), [](auto x, auto y) { return dfm::hypot(x, y); });\n}\nvoid BM_fastm_hypot_bounds(benchmark::State& state) {\n  bench::runBench2(state, hypotInputs(), sinInputs(), [](auto x, auto y) {\n    return dfm::hypot<float, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\nvoid BM_naive_hypot(benchmark::State& state) {\n  bench::runBench2(\n      state, hypotInputs(), sinInputs(), [](auto x, auto y) { return sqrtf(fmaf(x, x, y * y)); });\n}\nvoid BM_fastm_pow(benchmark::State& state) {\n  bench::runBench2(\n      state, powBaseInputs(), powExpInputs(), [](auto b, auto e) { return dfm::pow(b, e); });\n}\nvoid BM_fastm_pow_accurate(benchmark::State& state) {\n  bench::runBench2(state, powBaseInputs(), powExpInputs(), [](auto b, auto e) {\n    return dfm::pow<float, dfm::MaxAccuracyTraits>(b, e);\n  });\n}\n\n// frexp and ldexp use non-standard loop patterns — kept hand-written.\nvoid BM_fastm_frexp(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  int exp;\n  int64_t expSum = 0;\n  for (auto _ : state) {\n    (void)_;\n    sum += dfm::frexp(inputs[idx], &exp);\n    expSum += exp;\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << \" \" << expSum << std::endl;\n}\n\nvoid BM_fastm_ldexp(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  for (auto _ : state) {\n    (void)_;\n    sum += dfm::ldexp(inputs[idx], idx & 7);\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << std::endl;\n}\n\n// --- sincos / sincospi benchmarks ---\n\nvoid BM_fastm_sin_plus_cos(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::sin(x) + dfm::cos(x); });\n}\nvoid BM_fastm_sincos(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) {\n    float s, c;\n    dfm::sincos(x, &s, &c);\n    return s + c;\n  });\n}\nvoid BM_fastm_sinpi(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::sinpi(x); });\n}\nvoid BM_fastm_cospi(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) { return dfm::cospi(x); });\n}\nvoid BM_fastm_sincospi(benchmark::State& state) {\n  bench::runBench(state, sinInputs(), [](auto x) {\n    float s, c;\n    dfm::sincospi(x, &s, &c);\n    return s + c;\n  });\n}\n\n// --- Batch benchmarks: explicit SIMD via SseFloat (4-wide SSE) ---\n\n#if defined(__SSE4_1__)\n#include <dispenso/fast_math/float_traits_x86.h>\n\nstatic void BM_batch_sinf(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  alignas(16) float outputs[kNumInputs];\n  for (auto _ : state) {\n    (void)_;\n    for (size_t i = 0; i < kNumInputs; ++i) {\n      outputs[i] = ::sinf(inputs[i]);\n    }\n    benchmark::DoNotOptimize(outputs);\n  }\n  state.SetItemsProcessed(state.iterations() * kNumInputs);\n}\n\nstatic void BM_batch_sin_scalar(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  alignas(16) float outputs[kNumInputs];\n  for (auto _ : state) {\n    (void)_;\n    for (size_t i = 0; i < kNumInputs; ++i) {\n      outputs[i] = dfm::sin(inputs[i]);\n    }\n    benchmark::DoNotOptimize(outputs);\n  }\n  state.SetItemsProcessed(state.iterations() * kNumInputs);\n}\n\nstatic void BM_batch_sin_sse(benchmark::State& state) {\n  using namespace dispenso::fast_math;\n  const auto& inputs = sinInputs();\n  alignas(16) float outputs[kNumInputs];\n  for (auto _ : state) {\n    (void)_;\n    for (size_t i = 0; i < kNumInputs; i += 4) {\n      SseFloat x = _mm_loadu_ps(&inputs[i]);\n      SseFloat r = sin<SseFloat>(x);\n      _mm_storeu_ps(&outputs[i], r.v);\n    }\n    benchmark::DoNotOptimize(outputs);\n  }\n  state.SetItemsProcessed(state.iterations() * kNumInputs);\n}\n\nstatic void BM_batch_cos_scalar(benchmark::State& state) {\n  const auto& inputs = sinInputs();\n  alignas(16) float outputs[kNumInputs];\n  for (auto _ : state) {\n    (void)_;\n    for (size_t i = 0; i < kNumInputs; ++i) {\n      outputs[i] = dfm::cos(inputs[i]);\n    }\n    benchmark::DoNotOptimize(outputs);\n  }\n  state.SetItemsProcessed(state.iterations() * kNumInputs);\n}\n\nstatic void BM_batch_cos_sse(benchmark::State& state) {\n  using namespace dispenso::fast_math;\n  const auto& inputs = sinInputs();\n  alignas(16) float outputs[kNumInputs];\n  for (auto _ : state) {\n    (void)_;\n    for (size_t i = 0; i < kNumInputs; i += 4) {\n      SseFloat x = _mm_loadu_ps(&inputs[i]);\n      SseFloat r = cos<SseFloat>(x);\n      _mm_storeu_ps(&outputs[i], r.v);\n    }\n    benchmark::DoNotOptimize(outputs);\n  }\n  state.SetItemsProcessed(state.iterations() * kNumInputs);\n}\n\nBENCHMARK(BM_batch_sinf);\nBENCHMARK(BM_batch_sin_scalar);\nBENCHMARK(BM_batch_sin_sse);\nBENCHMARK(BM_batch_cos_scalar);\nBENCHMARK(BM_batch_cos_sse);\n#endif // __SSE4_1__\n\n// --- Registrations ---\n\nBENCHMARK(BM_acos);\nBENCHMARK(BM_fastm_acos);\nBENCHMARK(BM_asin);\nBENCHMARK(BM_fastm_asin);\nBENCHMARK(BM_atan);\nBENCHMARK(BM_fastm_atan);\nBENCHMARK(BM_atan2);\nBENCHMARK(BM_fastm_atan2);\nBENCHMARK(BM_fastm_atan2_bounds);\n\nBENCHMARK(BM_cbrt);\nBENCHMARK(BM_fastm_cbrt);\nBENCHMARK(BM_fastm_cbrt_accurate);\n\nBENCHMARK(BM_exp);\nBENCHMARK(BM_fastm_exp);\nBENCHMARK(BM_fastm_exp_bounds);\nBENCHMARK(BM_fastm_exp_accurate);\nBENCHMARK(BM_exp10);\nBENCHMARK(BM_fastm_exp10);\nBENCHMARK(BM_fastm_exp10_accurate);\nBENCHMARK(BM_exp2);\nBENCHMARK(BM_fastm_exp2);\nBENCHMARK(BM_fastm_exp2_accurate);\n\nBENCHMARK(BM_log);\nBENCHMARK(BM_fastm_log);\nBENCHMARK(BM_fastm_log_accurate);\nBENCHMARK(BM_log2);\nBENCHMARK(BM_fastm_log2);\nBENCHMARK(BM_fastm_log2_accurate);\nBENCHMARK(BM_log10);\nBENCHMARK(BM_fastm_log10);\nBENCHMARK(BM_fastm_log10_accurate);\n\nBENCHMARK(BM_sin);\nBENCHMARK(BM_fastm_sin);\nBENCHMARK(BM_fastm_sin_accurate);\nBENCHMARK(BM_cos);\nBENCHMARK(BM_fastm_cos);\nBENCHMARK(BM_fastm_cos_accurate);\n\nBENCHMARK(BM_frexp);\nBENCHMARK(BM_fastm_frexp);\nBENCHMARK(BM_ldexp);\nBENCHMARK(BM_fastm_ldexp);\n\nBENCHMARK(BM_tan);\nBENCHMARK(BM_fastm_tan);\nBENCHMARK(BM_fastm_tan_accurate);\n\nBENCHMARK(BM_hypot);\nBENCHMARK(BM_fastm_hypot);\nBENCHMARK(BM_naive_hypot);\nBENCHMARK(BM_fastm_hypot_bounds);\n\nBENCHMARK(BM_sin_plus_cos);\nBENCHMARK(BM_fastm_sin_plus_cos);\nBENCHMARK(BM_fastm_sincos);\nBENCHMARK(BM_fastm_sinpi);\nBENCHMARK(BM_fastm_cospi);\nBENCHMARK(BM_fastm_sincospi);\n\nBENCHMARK(BM_pow);\nBENCHMARK(BM_fastm_pow);\nBENCHMARK(BM_fastm_pow_accurate);\n\nBENCHMARK(BM_expm1);\nBENCHMARK(BM_fastm_expm1);\nBENCHMARK(BM_log1p);\nBENCHMARK(BM_fastm_log1p);\nBENCHMARK(BM_tanh);\nBENCHMARK(BM_fastm_tanh);\n"
  },
  {
    "path": "benchmarks/fast_math/erf_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Benchmark: erf S16 (float, t-substitution + inline exp) vs S21 (double, pure polynomial Estrin).\n// Also benchmarks libc erff for reference.\n\n#include <cmath>\n#include <cstdint>\n#include <iostream>\n#include <vector>\n\n#include <benchmark/benchmark.h>\n#include <dispenso/fast_math/fast_math.h>\n\n#if defined(__SSE4_1__)\n#include <immintrin.h>\n\n#if defined(__GNUC__) || defined(__clang__)\n#define UNUSED_VAR myLocalForLoopVar __attribute__((unused))\n#elif defined(_MSC_VER)\n#define UNUSED_VAR myLocalForLoopVar __pragma(warning(suppress : 4100))\n#else\n#define UNUSED_VAR myLocalForLoopVar\n#endif\n\nnamespace dfm = dispenso::fast_math;\n\nconstexpr size_t kNumInputs = 4096;\nconstexpr size_t kInputsMask = 4095;\n\n// --- Inputs: [-4, 4] ---\n\nconst std::vector<float>& erfScalarInputs() {\n  static std::vector<float> inputs = []() {\n    float delta = 8.0f / kNumInputs;\n    std::vector<float> inp;\n    for (float f = -4.0f; inp.size() < kNumInputs; f += delta) {\n      inp.push_back(f);\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\nconst std::vector<__m128>& erfSseInputs() {\n  static std::vector<__m128> inputs = []() {\n    float delta = 8.0f / kNumInputs;\n    std::vector<__m128> inp;\n    float f = -4.0f;\n    for (size_t i = 0; i < kNumInputs; ++i) {\n      inp.emplace_back(_mm_set_ps(f + 3 * delta, f + 2 * delta, f + delta, f));\n      f += 4 * delta;\n    }\n    return inp;\n  }();\n  return inputs;\n}\n\n#if defined(__AVX2__)\nconst std::vector<__m256>& erfAvxInputs() {\n  static std::vector<__m256> inputs = []() {\n    float delta = 8.0f / kNumInputs;\n    std::vector<__m256> inp;\n    float f = -4.0f;\n    for (size_t i = 0; i < kNumInputs; ++i) {\n      inp.emplace_back(_mm256_set_ps(\n          f + 7 * delta,\n          f + 6 * delta,\n          f + 5 * delta,\n          f + 4 * delta,\n          f + 3 * delta,\n          f + 2 * delta,\n          f + delta,\n          f));\n      f += 8 * delta;\n    }\n    return inp;\n  }();\n  return inputs;\n}\n#endif\n\n// --- S16: float, t-substitution + inline exp, 2 ULP ---\n\nstatic inline float erf_s16(float x) {\n  float ax = std::fabs(x);\n  float result;\n  if (ax >= 3.92f) {\n    result = 1.0f;\n  } else if (ax >= 0.875f) {\n    constexpr float p = 0.45f;\n    float t = 1.0f / std::fma(p, ax, 1.0f);\n\n    constexpr float c0 = 0x1.04873ep-2f;\n    constexpr float c1 = 0x1.f81fc6p-3f;\n    constexpr float c2 = 0x1.189f42p-2f;\n    constexpr float c3 = 0x1.15aaa6p-5f;\n    constexpr float c4 = 0x1.65d24ep-2f;\n    constexpr float c5 = -0x1.4432a4p-3f;\n\n    float poly =\n        t * std::fma(std::fma(std::fma(std::fma(std::fma(c5, t, c4), t, c3), t, c2), t, c1), t, c0);\n\n    float u = ax * ax;\n    constexpr float kLog2e = 0x1.715476p+0f;\n    constexpr float kLn2hi = 0x1.62e400p-1f;\n    constexpr float kLn2lo = 0x1.7f7d1cp-20f;\n    float k = std::floor(u * kLog2e);\n    float f = std::fma(k, -kLn2hi, u);\n    f = std::fma(k, -kLn2lo, f);\n    constexpr float e0 = 0x1.fffffep-1f, e1 = -0x1.ffff1ep-1f;\n    constexpr float e2 = 0x1.ffe314p-2f, e3 = -0x1.53f876p-3f;\n    constexpr float e4 = 0x1.462f16p-5f, e5 = -0x1.80e5b2p-8f;\n    float exp_neg_f =\n        std::fma(std::fma(std::fma(std::fma(std::fma(e5, f, e4), f, e3), f, e2), f, e1), f, e0);\n    int32_t ki = static_cast<int32_t>(k);\n    float pow2_neg_k = dfm::bit_cast<float>((127 - ki) << 23);\n\n    result = 1.0f - pow2_neg_k * exp_neg_f * poly;\n  } else {\n    constexpr float c0 = 0x1.20dd76p+0f;\n    constexpr float q0 = -0x1.812746p-2f, q1 = 0x1.ce2ec6p-4f, q2 = -0x1.b81edep-6f;\n    constexpr float q3 = 0x1.556b48p-8f, q4 = -0x1.b0255p-11f, q5 = 0x1.7149c8p-14f;\n    float u = ax * ax;\n    float q =\n        std::fma(std::fma(std::fma(std::fma(std::fma(q5, u, q4), u, q3), u, q2), u, q1), u, q0);\n    result = ax * std::fma(q, u, c0);\n  }\n  return x < 0.0f ? -result : result;\n}\n\n// --- S21: double, pure polynomial Estrin, 1 ULP ---\n\nstatic inline float erf_s21(float x) {\n  double ax = std::fabs(static_cast<double>(x));\n  double result;\n  if (ax >= 3.92) {\n    result = 1.0;\n  } else {\n    double u = ax * ax;\n\n    constexpr double c0 = 0x1.20dd74ce6dac1p0;\n    constexpr double c1 = -0x1.812728fedb0c3p-2;\n    constexpr double c2 = 0x1.ce2c679f0f94dp-4;\n    constexpr double c3 = -0x1.b81379b046993p-6;\n    constexpr double c4 = 0x1.55decae500c6cp-8;\n    constexpr double c5 = -0x1.bd402ca3b1d09p-11;\n    constexpr double c6 = 0x1.edfbbbd68d00ep-14;\n    constexpr double c7 = -0x1.d43f94bdfb90fp-17;\n    constexpr double c8 = 0x1.77643daca82f5p-20;\n    constexpr double c9 = -0x1.f276d5cf346ecp-24;\n    constexpr double c10 = 0x1.0a42c17eedcadp-27;\n    constexpr double c11 = -0x1.b999e591ae6bap-32;\n    constexpr double c12 = 0x1.0f73303821975p-36;\n    constexpr double c13 = -0x1.ce969a50741b3p-42;\n    constexpr double c14 = 0x1.e56af7f1b38e4p-48;\n    constexpr double c15 = -0x1.d6f65766c68e5p-55;\n\n    // Estrin's scheme: 4-level tree\n    double p0 = std::fma(c1, u, c0);\n    double p1 = std::fma(c3, u, c2);\n    double p2 = std::fma(c5, u, c4);\n    double p3 = std::fma(c7, u, c6);\n    double p4 = std::fma(c9, u, c8);\n    double p5 = std::fma(c11, u, c10);\n    double p6 = std::fma(c13, u, c12);\n    double p7 = std::fma(c15, u, c14);\n    double u2 = u * u;\n\n    double q0 = std::fma(p1, u2, p0);\n    double q1 = std::fma(p3, u2, p2);\n    double q2 = std::fma(p5, u2, p4);\n    double q3 = std::fma(p7, u2, p6);\n    double u4 = u2 * u2;\n\n    double r0 = std::fma(q1, u4, q0);\n    double r1 = std::fma(q3, u4, q2);\n    double u8 = u4 * u4;\n\n    double R = std::fma(r1, u8, r0);\n\n    result = ax * R;\n  }\n  return static_cast<float>(x < 0.0f ? -result : result);\n}\n\n// --- SSE S16 (float4, t-substitution + inline exp) ---\n\nstatic inline __m128 erf_s16_sse(__m128 x) {\n  __m128 ax = dfm::fabs(x);\n  __m128 sign = _mm_and_ps(x, _mm_set1_ps(-0.0f));\n\n  // Near-zero path: erf(x) = x * (c0 + u * Q(u))\n  __m128 u = _mm_mul_ps(ax, ax);\n  constexpr float nc0 = 0x1.20dd76p+0f;\n  constexpr float nq0 = -0x1.812746p-2f, nq1 = 0x1.ce2ec6p-4f, nq2 = -0x1.b81edep-6f;\n  constexpr float nq3 = 0x1.556b48p-8f, nq4 = -0x1.b0255p-11f, nq5 = 0x1.7149c8p-14f;\n  __m128 q = _mm_fmadd_ps(\n      _mm_fmadd_ps(\n          _mm_fmadd_ps(\n              _mm_fmadd_ps(\n                  _mm_fmadd_ps(_mm_set1_ps(nq5), u, _mm_set1_ps(nq4)), u, _mm_set1_ps(nq3)),\n              u,\n              _mm_set1_ps(nq2)),\n          u,\n          _mm_set1_ps(nq1)),\n      u,\n      _mm_set1_ps(nq0));\n  __m128 near_zero = _mm_mul_ps(ax, _mm_fmadd_ps(q, u, _mm_set1_ps(nc0)));\n\n  // Erfc path: erf(x) = 1 - t*P(t)*exp(-x^2)\n  constexpr float p = 0.45f;\n  __m128 t = _mm_div_ps(_mm_set1_ps(1.0f), _mm_fmadd_ps(_mm_set1_ps(p), ax, _mm_set1_ps(1.0f)));\n\n  constexpr float pc0 = 0x1.04873ep-2f, pc1 = 0x1.f81fc6p-3f, pc2 = 0x1.189f42p-2f;\n  constexpr float pc3 = 0x1.15aaa6p-5f, pc4 = 0x1.65d24ep-2f, pc5 = -0x1.4432a4p-3f;\n  __m128 ppoly = _mm_mul_ps(\n      t,\n      _mm_fmadd_ps(\n          _mm_fmadd_ps(\n              _mm_fmadd_ps(\n                  _mm_fmadd_ps(\n                      _mm_fmadd_ps(_mm_set1_ps(pc5), t, _mm_set1_ps(pc4)), t, _mm_set1_ps(pc3)),\n                  t,\n                  _mm_set1_ps(pc2)),\n              t,\n              _mm_set1_ps(pc1)),\n          t,\n          _mm_set1_ps(pc0)));\n\n  // Inline exp(-x^2): exp(-u) = 2^(-k) * exp(-f)\n  constexpr float kLog2e = 0x1.715476p+0f;\n  constexpr float kLn2hi = 0x1.62e400p-1f;\n  constexpr float kLn2lo = 0x1.7f7d1cp-20f;\n  __m128 kv = _mm_floor_ps(_mm_mul_ps(u, _mm_set1_ps(kLog2e)));\n  __m128 f = _mm_fmadd_ps(kv, _mm_set1_ps(-kLn2hi), u);\n  f = _mm_fmadd_ps(kv, _mm_set1_ps(-kLn2lo), f);\n  constexpr float e0 = 0x1.fffffep-1f, e1 = -0x1.ffff1ep-1f;\n  constexpr float e2 = 0x1.ffe314p-2f, e3 = -0x1.53f876p-3f;\n  constexpr float e4 = 0x1.462f16p-5f, e5 = -0x1.80e5b2p-8f;\n  __m128 exp_neg_f = _mm_fmadd_ps(\n      _mm_fmadd_ps(\n          _mm_fmadd_ps(\n              _mm_fmadd_ps(_mm_fmadd_ps(_mm_set1_ps(e5), f, _mm_set1_ps(e4)), f, _mm_set1_ps(e3)),\n              f,\n              _mm_set1_ps(e2)),\n          f,\n          _mm_set1_ps(e1)),\n      f,\n      _mm_set1_ps(e0));\n  __m128i ki = _mm_cvtps_epi32(kv);\n  __m128 pow2_neg_k = _mm_castsi128_ps(_mm_slli_epi32(_mm_sub_epi32(_mm_set1_epi32(127), ki), 23));\n\n  __m128 erfc_result =\n      _mm_sub_ps(_mm_set1_ps(1.0f), _mm_mul_ps(_mm_mul_ps(pow2_neg_k, exp_neg_f), ppoly));\n\n  // Blend: use near_zero for |x| < 0.875, erfc for |x| >= 0.875\n  __m128 use_erfc = _mm_cmpge_ps(ax, _mm_set1_ps(0.875f));\n  __m128 result = _mm_blendv_ps(near_zero, erfc_result, use_erfc);\n\n  // Clamp to 1 for |x| >= 3.92\n  __m128 saturated = _mm_cmpge_ps(ax, _mm_set1_ps(3.92f));\n  result = _mm_blendv_ps(result, _mm_set1_ps(1.0f), saturated);\n\n  // Restore sign\n  return _mm_or_ps(result, sign);\n}\n\n// --- SSE S21 (double poly Estrin, process 4 floats via 2x double2) ---\n\nstatic inline __m128 erf_s21_sse(__m128 x) {\n  __m128 ax_f = dfm::fabs(x);\n  __m128 sign = _mm_and_ps(x, _mm_set1_ps(-0.0f));\n\n  // Convert to double: split into low 2 and high 2\n  __m128d ax_lo = _mm_cvtps_pd(ax_f);\n  __m128d ax_hi = _mm_cvtps_pd(_mm_movehl_ps(ax_f, ax_f));\n\n  auto eval_poly = [](__m128d ax) -> __m128d {\n    __m128d u = _mm_mul_pd(ax, ax);\n\n    constexpr double c0 = 0x1.20dd74ce6dac1p0;\n    constexpr double c1 = -0x1.812728fedb0c3p-2;\n    constexpr double c2 = 0x1.ce2c679f0f94dp-4;\n    constexpr double c3 = -0x1.b81379b046993p-6;\n    constexpr double c4 = 0x1.55decae500c6cp-8;\n    constexpr double c5 = -0x1.bd402ca3b1d09p-11;\n    constexpr double c6 = 0x1.edfbbbd68d00ep-14;\n    constexpr double c7 = -0x1.d43f94bdfb90fp-17;\n    constexpr double c8 = 0x1.77643daca82f5p-20;\n    constexpr double c9 = -0x1.f276d5cf346ecp-24;\n    constexpr double c10 = 0x1.0a42c17eedcadp-27;\n    constexpr double c11 = -0x1.b999e591ae6bap-32;\n    constexpr double c12 = 0x1.0f73303821975p-36;\n    constexpr double c13 = -0x1.ce969a50741b3p-42;\n    constexpr double c14 = 0x1.e56af7f1b38e4p-48;\n    constexpr double c15 = -0x1.d6f65766c68e5p-55;\n\n    // Estrin level 0\n    __m128d p0 = _mm_fmadd_pd(_mm_set1_pd(c1), u, _mm_set1_pd(c0));\n    __m128d p1 = _mm_fmadd_pd(_mm_set1_pd(c3), u, _mm_set1_pd(c2));\n    __m128d p2 = _mm_fmadd_pd(_mm_set1_pd(c5), u, _mm_set1_pd(c4));\n    __m128d p3 = _mm_fmadd_pd(_mm_set1_pd(c7), u, _mm_set1_pd(c6));\n    __m128d p4 = _mm_fmadd_pd(_mm_set1_pd(c9), u, _mm_set1_pd(c8));\n    __m128d p5 = _mm_fmadd_pd(_mm_set1_pd(c11), u, _mm_set1_pd(c10));\n    __m128d p6 = _mm_fmadd_pd(_mm_set1_pd(c13), u, _mm_set1_pd(c12));\n    __m128d p7 = _mm_fmadd_pd(_mm_set1_pd(c15), u, _mm_set1_pd(c14));\n    __m128d u2 = _mm_mul_pd(u, u);\n\n    // Level 1\n    __m128d q0 = _mm_fmadd_pd(p1, u2, p0);\n    __m128d q1 = _mm_fmadd_pd(p3, u2, p2);\n    __m128d q2 = _mm_fmadd_pd(p5, u2, p4);\n    __m128d q3 = _mm_fmadd_pd(p7, u2, p6);\n    __m128d u4 = _mm_mul_pd(u2, u2);\n\n    // Level 2\n    __m128d r0 = _mm_fmadd_pd(q1, u4, q0);\n    __m128d r1 = _mm_fmadd_pd(q3, u4, q2);\n    __m128d u8 = _mm_mul_pd(u4, u4);\n\n    // Level 3\n    __m128d R = _mm_fmadd_pd(r1, u8, r0);\n\n    return _mm_mul_pd(ax, R);\n  };\n\n  __m128d res_lo = eval_poly(ax_lo);\n  __m128d res_hi = eval_poly(ax_hi);\n\n  // Convert back to float\n  __m128 result = _mm_movelh_ps(_mm_cvtpd_ps(res_lo), _mm_cvtpd_ps(res_hi));\n\n  // Clamp to 1 for |x| >= 3.92\n  __m128 saturated = _mm_cmpge_ps(ax_f, _mm_set1_ps(3.92f));\n  result = _mm_blendv_ps(result, _mm_set1_ps(1.0f), saturated);\n\n  // Restore sign\n  return _mm_or_ps(result, sign);\n}\n\nstatic void consumeSum(__m128 sum) {\n  alignas(16) float buf[4];\n  _mm_store_ps(buf, sum);\n  std::cout << buf[0] + buf[1] + buf[2] + buf[3] << std::endl;\n}\n\n// --- Scalar benchmarks ---\n\nvoid BM_erf_libc(benchmark::State& state) {\n  const auto& inputs = erfScalarInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  for (auto UNUSED_VAR : state) {\n    sum += ::erff(inputs[idx]);\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << std::endl;\n}\n\nvoid BM_erf_s16_scalar(benchmark::State& state) {\n  const auto& inputs = erfScalarInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  for (auto UNUSED_VAR : state) {\n    sum += erf_s16(inputs[idx]);\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << std::endl;\n}\n\nvoid BM_erf_s21_scalar(benchmark::State& state) {\n  const auto& inputs = erfScalarInputs();\n  size_t idx = 0;\n  float sum = 0.0f;\n  for (auto UNUSED_VAR : state) {\n    sum += erf_s21(inputs[idx]);\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations());\n  std::cout << sum << std::endl;\n}\n\n// --- SSE benchmarks ---\n\nvoid BM_erf_s16_sse(benchmark::State& state) {\n  const auto& inputs = erfSseInputs();\n  size_t idx = 0;\n  __m128 sum = _mm_setzero_ps();\n  for (auto UNUSED_VAR : state) {\n    sum = _mm_add_ps(sum, erf_s16_sse(inputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 4);\n  consumeSum(sum);\n}\n\nvoid BM_erf_s21_sse(benchmark::State& state) {\n  const auto& inputs = erfSseInputs();\n  size_t idx = 0;\n  __m128 sum = _mm_setzero_ps();\n  for (auto UNUSED_VAR : state) {\n    sum = _mm_add_ps(sum, erf_s21_sse(inputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 4);\n  consumeSum(sum);\n}\n\nBENCHMARK(BM_erf_libc);\nBENCHMARK(BM_erf_s16_scalar);\nBENCHMARK(BM_erf_s21_scalar);\nBENCHMARK(BM_erf_s16_sse);\nBENCHMARK(BM_erf_s21_sse);\n\n#if defined(__AVX2__)\n\nstatic void consumeSum256(__m256 sum) {\n  alignas(32) float buf[8];\n  _mm256_store_ps(buf, sum);\n  float s = 0;\n  for (int i = 0; i < 8; ++i)\n    s += buf[i];\n  std::cout << s << std::endl;\n}\n\n// --- AVX S16 ---\n\nstatic inline __m256 erf_s16_avx(__m256 x) {\n  __m256 ax = dfm::fabs(x);\n  __m256 sign = _mm256_and_ps(x, _mm256_set1_ps(-0.0f));\n\n  // Near-zero path\n  __m256 u = _mm256_mul_ps(ax, ax);\n  constexpr float nc0 = 0x1.20dd76p+0f;\n  constexpr float nq0 = -0x1.812746p-2f, nq1 = 0x1.ce2ec6p-4f, nq2 = -0x1.b81edep-6f;\n  constexpr float nq3 = 0x1.556b48p-8f, nq4 = -0x1.b0255p-11f, nq5 = 0x1.7149c8p-14f;\n  __m256 q = _mm256_fmadd_ps(\n      _mm256_fmadd_ps(\n          _mm256_fmadd_ps(\n              _mm256_fmadd_ps(\n                  _mm256_fmadd_ps(_mm256_set1_ps(nq5), u, _mm256_set1_ps(nq4)),\n                  u,\n                  _mm256_set1_ps(nq3)),\n              u,\n              _mm256_set1_ps(nq2)),\n          u,\n          _mm256_set1_ps(nq1)),\n      u,\n      _mm256_set1_ps(nq0));\n  __m256 near_zero = _mm256_mul_ps(ax, _mm256_fmadd_ps(q, u, _mm256_set1_ps(nc0)));\n\n  // Erfc path\n  constexpr float p = 0.45f;\n  __m256 t = _mm256_div_ps(\n      _mm256_set1_ps(1.0f), _mm256_fmadd_ps(_mm256_set1_ps(p), ax, _mm256_set1_ps(1.0f)));\n\n  constexpr float pc0 = 0x1.04873ep-2f, pc1 = 0x1.f81fc6p-3f, pc2 = 0x1.189f42p-2f;\n  constexpr float pc3 = 0x1.15aaa6p-5f, pc4 = 0x1.65d24ep-2f, pc5 = -0x1.4432a4p-3f;\n  __m256 ppoly = _mm256_mul_ps(\n      t,\n      _mm256_fmadd_ps(\n          _mm256_fmadd_ps(\n              _mm256_fmadd_ps(\n                  _mm256_fmadd_ps(\n                      _mm256_fmadd_ps(_mm256_set1_ps(pc5), t, _mm256_set1_ps(pc4)),\n                      t,\n                      _mm256_set1_ps(pc3)),\n                  t,\n                  _mm256_set1_ps(pc2)),\n              t,\n              _mm256_set1_ps(pc1)),\n          t,\n          _mm256_set1_ps(pc0)));\n\n  // Inline exp(-x^2)\n  constexpr float kLog2e = 0x1.715476p+0f;\n  constexpr float kLn2hi = 0x1.62e400p-1f;\n  constexpr float kLn2lo = 0x1.7f7d1cp-20f;\n  __m256 kv = _mm256_floor_ps(_mm256_mul_ps(u, _mm256_set1_ps(kLog2e)));\n  __m256 f = _mm256_fmadd_ps(kv, _mm256_set1_ps(-kLn2hi), u);\n  f = _mm256_fmadd_ps(kv, _mm256_set1_ps(-kLn2lo), f);\n  constexpr float e0 = 0x1.fffffep-1f, e1 = -0x1.ffff1ep-1f;\n  constexpr float e2 = 0x1.ffe314p-2f, e3 = -0x1.53f876p-3f;\n  constexpr float e4 = 0x1.462f16p-5f, e5 = -0x1.80e5b2p-8f;\n  __m256 exp_neg_f = _mm256_fmadd_ps(\n      _mm256_fmadd_ps(\n          _mm256_fmadd_ps(\n              _mm256_fmadd_ps(\n                  _mm256_fmadd_ps(_mm256_set1_ps(e5), f, _mm256_set1_ps(e4)),\n                  f,\n                  _mm256_set1_ps(e3)),\n              f,\n              _mm256_set1_ps(e2)),\n          f,\n          _mm256_set1_ps(e1)),\n      f,\n      _mm256_set1_ps(e0));\n  __m256i ki = _mm256_cvtps_epi32(kv);\n  __m256 pow2_neg_k =\n      _mm256_castsi256_ps(_mm256_slli_epi32(_mm256_sub_epi32(_mm256_set1_epi32(127), ki), 23));\n\n  __m256 erfc_result = _mm256_sub_ps(\n      _mm256_set1_ps(1.0f), _mm256_mul_ps(_mm256_mul_ps(pow2_neg_k, exp_neg_f), ppoly));\n\n  // Blend\n  __m256 use_erfc = _mm256_cmp_ps(ax, _mm256_set1_ps(0.875f), _CMP_GE_OQ);\n  __m256 result = _mm256_blendv_ps(near_zero, erfc_result, use_erfc);\n\n  __m256 saturated = _mm256_cmp_ps(ax, _mm256_set1_ps(3.92f), _CMP_GE_OQ);\n  result = _mm256_blendv_ps(result, _mm256_set1_ps(1.0f), saturated);\n\n  return _mm256_or_ps(result, sign);\n}\n\n// --- AVX S21 (process 8 floats via 4x double2) ---\n\nstatic inline __m256 erf_s21_avx(__m256 x) {\n  __m256 ax_f = dfm::fabs(x);\n  __m256 sign = _mm256_and_ps(x, _mm256_set1_ps(-0.0f));\n\n  // Split 8 floats into 4 groups of 2 doubles\n  __m128 lo4 = _mm256_castps256_ps128(ax_f);\n  __m128 hi4 = _mm256_extractf128_ps(ax_f, 1);\n  __m128d ax_0 = _mm_cvtps_pd(lo4);\n  __m128d ax_1 = _mm_cvtps_pd(_mm_movehl_ps(lo4, lo4));\n  __m128d ax_2 = _mm_cvtps_pd(hi4);\n  __m128d ax_3 = _mm_cvtps_pd(_mm_movehl_ps(hi4, hi4));\n\n  auto eval_poly = [](__m128d ax) -> __m128d {\n    __m128d u = _mm_mul_pd(ax, ax);\n    constexpr double c0 = 0x1.20dd74ce6dac1p0;\n    constexpr double c1 = -0x1.812728fedb0c3p-2;\n    constexpr double c2 = 0x1.ce2c679f0f94dp-4;\n    constexpr double c3 = -0x1.b81379b046993p-6;\n    constexpr double c4 = 0x1.55decae500c6cp-8;\n    constexpr double c5 = -0x1.bd402ca3b1d09p-11;\n    constexpr double c6 = 0x1.edfbbbd68d00ep-14;\n    constexpr double c7 = -0x1.d43f94bdfb90fp-17;\n    constexpr double c8 = 0x1.77643daca82f5p-20;\n    constexpr double c9 = -0x1.f276d5cf346ecp-24;\n    constexpr double c10 = 0x1.0a42c17eedcadp-27;\n    constexpr double c11 = -0x1.b999e591ae6bap-32;\n    constexpr double c12 = 0x1.0f73303821975p-36;\n    constexpr double c13 = -0x1.ce969a50741b3p-42;\n    constexpr double c14 = 0x1.e56af7f1b38e4p-48;\n    constexpr double c15 = -0x1.d6f65766c68e5p-55;\n\n    __m128d p0 = _mm_fmadd_pd(_mm_set1_pd(c1), u, _mm_set1_pd(c0));\n    __m128d p1 = _mm_fmadd_pd(_mm_set1_pd(c3), u, _mm_set1_pd(c2));\n    __m128d p2 = _mm_fmadd_pd(_mm_set1_pd(c5), u, _mm_set1_pd(c4));\n    __m128d p3 = _mm_fmadd_pd(_mm_set1_pd(c7), u, _mm_set1_pd(c6));\n    __m128d p4 = _mm_fmadd_pd(_mm_set1_pd(c9), u, _mm_set1_pd(c8));\n    __m128d p5 = _mm_fmadd_pd(_mm_set1_pd(c11), u, _mm_set1_pd(c10));\n    __m128d p6 = _mm_fmadd_pd(_mm_set1_pd(c13), u, _mm_set1_pd(c12));\n    __m128d p7 = _mm_fmadd_pd(_mm_set1_pd(c15), u, _mm_set1_pd(c14));\n    __m128d u2 = _mm_mul_pd(u, u);\n\n    __m128d q0 = _mm_fmadd_pd(p1, u2, p0);\n    __m128d q1 = _mm_fmadd_pd(p3, u2, p2);\n    __m128d q2 = _mm_fmadd_pd(p5, u2, p4);\n    __m128d q3 = _mm_fmadd_pd(p7, u2, p6);\n    __m128d u4 = _mm_mul_pd(u2, u2);\n\n    __m128d r0 = _mm_fmadd_pd(q1, u4, q0);\n    __m128d r1 = _mm_fmadd_pd(q3, u4, q2);\n    __m128d u8 = _mm_mul_pd(u4, u4);\n\n    __m128d R = _mm_fmadd_pd(r1, u8, r0);\n    return _mm_mul_pd(ax, R);\n  };\n\n  __m128d res_0 = eval_poly(ax_0);\n  __m128d res_1 = eval_poly(ax_1);\n  __m128d res_2 = eval_poly(ax_2);\n  __m128d res_3 = eval_poly(ax_3);\n\n  // Convert back: 4x double2 -> 2x float4 -> 1x float8\n  __m128 lo_f = _mm_movelh_ps(_mm_cvtpd_ps(res_0), _mm_cvtpd_ps(res_1));\n  __m128 hi_f = _mm_movelh_ps(_mm_cvtpd_ps(res_2), _mm_cvtpd_ps(res_3));\n  __m256 result = _mm256_set_m128(hi_f, lo_f);\n\n  // Clamp\n  __m256 saturated = _mm256_cmp_ps(ax_f, _mm256_set1_ps(3.92f), _CMP_GE_OQ);\n  result = _mm256_blendv_ps(result, _mm256_set1_ps(1.0f), saturated);\n\n  return _mm256_or_ps(result, sign);\n}\n\nvoid BM_erf_s16_avx(benchmark::State& state) {\n  const auto& inputs = erfAvxInputs();\n  size_t idx = 0;\n  __m256 sum = _mm256_setzero_ps();\n  for (auto UNUSED_VAR : state) {\n    sum = _mm256_add_ps(sum, erf_s16_avx(inputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 8);\n  consumeSum256(sum);\n}\n\nvoid BM_erf_s21_avx(benchmark::State& state) {\n  const auto& inputs = erfAvxInputs();\n  size_t idx = 0;\n  __m256 sum = _mm256_setzero_ps();\n  for (auto UNUSED_VAR : state) {\n    sum = _mm256_add_ps(sum, erf_s21_avx(inputs[idx]));\n    idx = (idx + 1) & kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 8);\n  consumeSum256(sum);\n}\n\nBENCHMARK(BM_erf_s16_avx);\nBENCHMARK(BM_erf_s21_avx);\n\n#endif // __AVX2__\n\n#else // !__SSE4_1__\n\nint main() {\n  std::cout << \"SSE4.1 not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // __SSE4_1__\n"
  },
  {
    "path": "benchmarks/fast_math/hwy_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\n#if __has_include(\"hwy/highway.h\")\n#include \"hwy/contrib/math/math-inl.h\"\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\nnamespace hn = hwy::HWY_NAMESPACE;\nusing Flt = dfm::HwyFloat;\nusing HwyFloatTag = dfm::HwyFloatTag;\n\nstruct BoundsTraits {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;\n};\n\n// --- One-arg benchmarks ---\n\nvoid BM_sin_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_sin_hwy_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::sin<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_cos_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_cos_hwy_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::cos<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_tan_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_atan_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_acos_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_asin_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::asin(x); });\n}\n\nvoid BM_exp_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_exp_hwy_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) {\n    return dfm::exp<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_exp_hwy_bounds(benchmark::State& state) {\n  bench::runBench(\n      state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp<Flt, BoundsTraits>(x); });\n}\nvoid BM_exp2_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_exp10_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_expm1_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::expm1(x); });\n}\n\nvoid BM_log_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_log_hwy_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::log<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_log2_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_log10_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_log1p_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::log1p(hn::Abs(x.v)); });\n}\n\nvoid BM_cbrt_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::cbrt(x); });\n}\nvoid BM_cbrt_hwy_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::cbrt<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\n\nvoid BM_frexp_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    dfm::IntType_t<Flt> e;\n    return dfm::frexp(x, &e);\n  });\n}\nvoid BM_ldexp_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    const hn::RebindToSigned<HwyFloatTag> di;\n    return dfm::ldexp(x, hn::Set(di, 3));\n  });\n}\n\nvoid BM_tanh_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::tanhInputs<Flt>(), [](auto x) { return dfm::tanh(x); });\n}\nvoid BM_erf_hwy(benchmark::State& state) {\n  bench::runBench(state, bench::erfInputs<Flt>(), [](auto x) { return dfm::erf(x); });\n}\n\n// --- Two-arg benchmarks ---\n\nvoid BM_atan2_hwy(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return dfm::atan2(y, x);\n  });\n}\n\nvoid BM_hypot_hwy(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot(x, y);\n  });\n}\nvoid BM_hypot_hwy_bounds(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\n\n// --- Highway contrib/math comparison benchmarks ---\n\nvoid BM_sin_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::sinInputs<Flt>(), [](auto x) { return hn::Sin(HwyFloatTag(), x.v); });\n}\nvoid BM_cos_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::sinInputs<Flt>(), [](auto x) { return hn::Cos(HwyFloatTag(), x.v); });\n}\nvoid BM_exp_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::expInputs<Flt>(), [](auto x) { return hn::Exp(HwyFloatTag(), x.v); });\n}\nvoid BM_exp2_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::expInputs<Flt>(), [](auto x) { return hn::Exp2(HwyFloatTag(), x.v); });\n}\nvoid BM_log_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return hn::Log(HwyFloatTag(), x.v); });\n}\nvoid BM_log2_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return hn::Log2(HwyFloatTag(), x.v); });\n}\nvoid BM_log10_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return hn::Log10(HwyFloatTag(), x.v); });\n}\nvoid BM_atan_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::sinInputs<Flt>(), [](auto x) { return hn::Atan(HwyFloatTag(), x.v); });\n}\nvoid BM_acos_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::acosInputs<Flt>(), [](auto x) { return hn::Acos(HwyFloatTag(), x.v); });\n}\nvoid BM_asin_hwy_contrib(benchmark::State& state) {\n  bench::runBench(\n      state, bench::acosInputs<Flt>(), [](auto x) { return hn::Asin(HwyFloatTag(), x.v); });\n}\nvoid BM_atan2_hwy_contrib(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return hn::Atan2(HwyFloatTag(), y.v, x.v);\n  });\n}\n\n// --- Registrations ---\n\nBENCHMARK(BM_sin_hwy);\nBENCHMARK(BM_sin_hwy_accurate);\nBENCHMARK(BM_sin_hwy_contrib);\nBENCHMARK(BM_cos_hwy);\nBENCHMARK(BM_cos_hwy_accurate);\nBENCHMARK(BM_cos_hwy_contrib);\nBENCHMARK(BM_tan_hwy);\nBENCHMARK(BM_atan_hwy);\nBENCHMARK(BM_atan_hwy_contrib);\nBENCHMARK(BM_acos_hwy);\nBENCHMARK(BM_acos_hwy_contrib);\nBENCHMARK(BM_asin_hwy);\nBENCHMARK(BM_asin_hwy_contrib);\nBENCHMARK(BM_exp_hwy);\nBENCHMARK(BM_exp_hwy_accurate);\nBENCHMARK(BM_exp_hwy_bounds);\nBENCHMARK(BM_exp_hwy_contrib);\nBENCHMARK(BM_exp2_hwy);\nBENCHMARK(BM_exp2_hwy_contrib);\nBENCHMARK(BM_exp10_hwy);\nBENCHMARK(BM_expm1_hwy);\nBENCHMARK(BM_log_hwy);\nBENCHMARK(BM_log_hwy_accurate);\nBENCHMARK(BM_log_hwy_contrib);\nBENCHMARK(BM_log2_hwy);\nBENCHMARK(BM_log2_hwy_contrib);\nBENCHMARK(BM_log10_hwy);\nBENCHMARK(BM_log10_hwy_contrib);\nBENCHMARK(BM_log1p_hwy);\nBENCHMARK(BM_cbrt_hwy);\nBENCHMARK(BM_cbrt_hwy_accurate);\nBENCHMARK(BM_frexp_hwy);\nBENCHMARK(BM_ldexp_hwy);\nBENCHMARK(BM_tanh_hwy);\nBENCHMARK(BM_erf_hwy);\nBENCHMARK(BM_atan2_hwy);\nBENCHMARK(BM_atan2_hwy_contrib);\nBENCHMARK(BM_hypot_hwy);\nBENCHMARK(BM_hypot_hwy_bounds);\n\n#else // !__has_include(\"hwy/highway.h\")\n\nint main() {\n  std::cout << \"Highway not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // __has_include(\"hwy/highway.h\")\n"
  },
  {
    "path": "benchmarks/fast_math/neon_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\n#if defined(__aarch64__)\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\nusing Flt = float32x4_t;\n\n// --- One-arg benchmarks ---\n\nvoid BM_sin_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_cos_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_tan_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_atan_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_acos_neon(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_asin_neon(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::asin(x); });\n}\n\nvoid BM_exp_neon(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_exp2_neon(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_exp10_neon(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_expm1_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::expm1(x); });\n}\n\nvoid BM_log_neon(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_log2_neon(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_log10_neon(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_log1p_neon(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](Flt x) { return dfm::log1p(vabsq_f32(x)); });\n}\n\nvoid BM_cbrt_neon(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::cbrt(x); });\n}\n\nvoid BM_frexp_neon(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    dfm::IntType_t<Flt> e;\n    return dfm::frexp(x, &e);\n  });\n}\nvoid BM_ldexp_neon(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return dfm::ldexp(x, vdupq_n_s32(3)); });\n}\n\nvoid BM_tanh_neon(benchmark::State& state) {\n  bench::runBench(state, bench::tanhInputs<Flt>(), [](auto x) { return dfm::tanh(x); });\n}\nvoid BM_erf_neon(benchmark::State& state) {\n  bench::runBench(state, bench::erfInputs<Flt>(), [](auto x) { return dfm::erf(x); });\n}\n\n// --- Two-arg benchmarks ---\n\nvoid BM_atan2_neon(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return dfm::atan2(y, x);\n  });\n}\n\nvoid BM_hypot_neon(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot(x, y);\n  });\n}\nvoid BM_hypot_neon_bounds(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\n\nvoid BM_pow_neon(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow(b, e);\n      });\n}\nvoid BM_pow_neon_accurate(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow<Flt, dfm::MaxAccuracyTraits>(b, e);\n      });\n}\nvoid BM_pow_neon_scalar_exp(benchmark::State& state) {\n  bench::runBench(state, bench::powBaseInputs<Flt>(), [](auto x) { return dfm::pow(x, 2.5f); });\n}\n\n// --- Libc-packed comparison (NEON-specific, kept hand-written) ---\n\nvoid BM_pow_libc_neon(benchmark::State& state) {\n  const auto& bases = bench::powBaseInputs<Flt>();\n  const auto& exps = bench::powExpInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = vdupq_n_f32(0.0f);\n  for (auto _ : state) {\n    (void)_;\n    alignas(16) float x[4], y[4], r[4];\n    vst1q_f32(x, bases[idx]);\n    vst1q_f32(y, exps[idx]);\n    for (int32_t i = 0; i < 4; ++i) {\n      r[i] = ::powf(x[i], y[i]);\n    }\n    sum = vaddq_f32(sum, vld1q_f32(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 4);\n  bench::consumeResult(sum);\n}\n\n// --- Registrations ---\n\nBENCHMARK(BM_sin_neon);\nBENCHMARK(BM_cos_neon);\nBENCHMARK(BM_tan_neon);\nBENCHMARK(BM_atan_neon);\nBENCHMARK(BM_acos_neon);\nBENCHMARK(BM_asin_neon);\nBENCHMARK(BM_exp_neon);\nBENCHMARK(BM_exp2_neon);\nBENCHMARK(BM_exp10_neon);\nBENCHMARK(BM_expm1_neon);\nBENCHMARK(BM_log_neon);\nBENCHMARK(BM_log2_neon);\nBENCHMARK(BM_log10_neon);\nBENCHMARK(BM_log1p_neon);\nBENCHMARK(BM_cbrt_neon);\nBENCHMARK(BM_frexp_neon);\nBENCHMARK(BM_ldexp_neon);\nBENCHMARK(BM_tanh_neon);\nBENCHMARK(BM_erf_neon);\nBENCHMARK(BM_atan2_neon);\nBENCHMARK(BM_hypot_neon);\nBENCHMARK(BM_hypot_neon_bounds);\nBENCHMARK(BM_pow_neon);\nBENCHMARK(BM_pow_neon_accurate);\nBENCHMARK(BM_pow_neon_scalar_exp);\nBENCHMARK(BM_pow_libc_neon);\n\n#else // !defined(__aarch64__)\n\nint main() {\n  std::cout << \"AArch64 NEON not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // defined(__aarch64__)\n"
  },
  {
    "path": "benchmarks/fast_math/sse_benchmarks.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"benchmark_helpers.h\"\n\n#if defined(__SSE4_1__)\n\nnamespace dfm = dispenso::fast_math;\nnamespace bench = dispenso::fast_math::bench;\nusing Flt = __m128;\n\nstruct BoundsTraits {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;\n};\n\n// --- One-arg benchmarks ---\n\nvoid BM_sin_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::sin(x); });\n}\nvoid BM_sin_sse_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::sin<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_cos_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::cos(x); });\n}\nvoid BM_cos_sse_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) {\n    return dfm::cos<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_tan_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::tan(x); });\n}\nvoid BM_atan_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::atan(x); });\n}\nvoid BM_acos_sse(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::acos(x); });\n}\nvoid BM_asin_sse(benchmark::State& state) {\n  bench::runBench(state, bench::acosInputs<Flt>(), [](auto x) { return dfm::asin(x); });\n}\n\nvoid BM_exp_sse(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp(x); });\n}\nvoid BM_exp_sse_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) {\n    return dfm::exp<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_exp_sse_bounds(benchmark::State& state) {\n  bench::runBench(\n      state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp<Flt, BoundsTraits>(x); });\n}\nvoid BM_exp2_sse(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp2(x); });\n}\nvoid BM_exp10_sse(benchmark::State& state) {\n  bench::runBench(state, bench::expInputs<Flt>(), [](auto x) { return dfm::exp10(x); });\n}\nvoid BM_expm1_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](auto x) { return dfm::expm1(x); });\n}\n\nvoid BM_log_sse(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log(x); });\n}\nvoid BM_log_sse_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::log<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\nvoid BM_log2_sse(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log2(x); });\n}\nvoid BM_log10_sse(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::log10(x); });\n}\nvoid BM_log1p_sse(benchmark::State& state) {\n  bench::runBench(state, bench::sinInputs<Flt>(), [](Flt x) {\n    Flt ax = _mm_andnot_ps(_mm_set1_ps(-0.0f), x);\n    return dfm::log1p(ax);\n  });\n}\n\nvoid BM_cbrt_sse(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) { return dfm::cbrt(x); });\n}\nvoid BM_cbrt_sse_accurate(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    return dfm::cbrt<Flt, dfm::MaxAccuracyTraits>(x);\n  });\n}\n\nvoid BM_frexp_sse(benchmark::State& state) {\n  bench::runBench(state, bench::logInputs<Flt>(), [](auto x) {\n    dfm::IntType_t<Flt> e;\n    return dfm::frexp(x, &e);\n  });\n}\nvoid BM_ldexp_sse(benchmark::State& state) {\n  bench::runBench(\n      state, bench::logInputs<Flt>(), [](auto x) { return dfm::ldexp(x, _mm_set1_epi32(3)); });\n}\n\nvoid BM_tanh_sse(benchmark::State& state) {\n  bench::runBench(state, bench::tanhInputs<Flt>(), [](auto x) { return dfm::tanh(x); });\n}\nvoid BM_erf_sse(benchmark::State& state) {\n  bench::runBench(state, bench::erfInputs<Flt>(), [](auto x) { return dfm::erf(x); });\n}\n\n// --- Two-arg benchmarks ---\n\nvoid BM_atan2_sse(benchmark::State& state) {\n  bench::runBench2(state, bench::expInputs<Flt>(), bench::sinInputs<Flt>(), [](auto y, auto x) {\n    return dfm::atan2(y, x);\n  });\n}\n\nvoid BM_hypot_sse(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot(x, y);\n  });\n}\nvoid BM_hypot_sse_bounds(benchmark::State& state) {\n  bench::runBench2(state, bench::hypotInputs<Flt>(), bench::sinInputs<Flt>(), [](auto x, auto y) {\n    return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n  });\n}\n\nvoid BM_pow_sse(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow(b, e);\n      });\n}\nvoid BM_pow_sse_accurate(benchmark::State& state) {\n  bench::runBench2(\n      state, bench::powBaseInputs<Flt>(), bench::powExpInputs<Flt>(), [](auto b, auto e) {\n        return dfm::pow<Flt, dfm::MaxAccuracyTraits>(b, e);\n      });\n}\nvoid BM_pow_sse_scalar_exp(benchmark::State& state) {\n  bench::runBench(state, bench::powBaseInputs<Flt>(), [](auto x) { return dfm::pow(x, 2.5f); });\n}\n\n// --- Libc-packed comparisons (SSE-specific, kept hand-written) ---\n\nvoid BM_hypot_libc(benchmark::State& state) {\n  const auto& inputs = bench::hypotInputs<Flt>();\n  const auto& inputs2 = bench::sinInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = _mm_setzero_ps();\n  for (auto _ : state) {\n    (void)_;\n    alignas(16) float x[4], y[4], r[4];\n    _mm_store_ps(x, inputs[idx]);\n    _mm_store_ps(y, inputs2[idx]);\n    r[0] = ::hypotf(x[0], y[0]);\n    r[1] = ::hypotf(x[1], y[1]);\n    r[2] = ::hypotf(x[2], y[2]);\n    r[3] = ::hypotf(x[3], y[3]);\n    sum = _mm_add_ps(sum, _mm_load_ps(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 4);\n  bench::consumeResult(sum);\n}\n\nvoid BM_pow_libc_sse(benchmark::State& state) {\n  const auto& bases = bench::powBaseInputs<Flt>();\n  const auto& exps = bench::powExpInputs<Flt>();\n  size_t idx = 0;\n  Flt sum = _mm_setzero_ps();\n  for (auto _ : state) {\n    (void)_;\n    alignas(16) float x[4], y[4], r[4];\n    _mm_store_ps(x, bases[idx]);\n    _mm_store_ps(y, exps[idx]);\n    r[0] = ::powf(x[0], y[0]);\n    r[1] = ::powf(x[1], y[1]);\n    r[2] = ::powf(x[2], y[2]);\n    r[3] = ::powf(x[3], y[3]);\n    sum = _mm_add_ps(sum, _mm_load_ps(r));\n    idx = (idx + 1) & bench::kInputsMask;\n  }\n  state.SetItemsProcessed(state.iterations() * 4);\n  bench::consumeResult(sum);\n}\n\n// --- Registrations ---\n\nBENCHMARK(BM_sin_sse);\nBENCHMARK(BM_sin_sse_accurate);\nBENCHMARK(BM_cos_sse);\nBENCHMARK(BM_cos_sse_accurate);\nBENCHMARK(BM_tan_sse);\nBENCHMARK(BM_atan_sse);\nBENCHMARK(BM_acos_sse);\nBENCHMARK(BM_asin_sse);\nBENCHMARK(BM_exp_sse);\nBENCHMARK(BM_exp_sse_accurate);\nBENCHMARK(BM_exp_sse_bounds);\nBENCHMARK(BM_exp2_sse);\nBENCHMARK(BM_exp10_sse);\nBENCHMARK(BM_expm1_sse);\nBENCHMARK(BM_log_sse);\nBENCHMARK(BM_log_sse_accurate);\nBENCHMARK(BM_log2_sse);\nBENCHMARK(BM_log10_sse);\nBENCHMARK(BM_log1p_sse);\nBENCHMARK(BM_cbrt_sse);\nBENCHMARK(BM_cbrt_sse_accurate);\nBENCHMARK(BM_frexp_sse);\nBENCHMARK(BM_ldexp_sse);\nBENCHMARK(BM_tanh_sse);\nBENCHMARK(BM_erf_sse);\nBENCHMARK(BM_atan2_sse);\nBENCHMARK(BM_hypot_sse);\nBENCHMARK(BM_hypot_sse_bounds);\nBENCHMARK(BM_hypot_libc);\nBENCHMARK(BM_pow_sse);\nBENCHMARK(BM_pow_sse_accurate);\nBENCHMARK(BM_pow_sse_scalar_exp);\nBENCHMARK(BM_pow_libc_sse);\n\n#else // !defined(__SSE4_1__)\n\nint main() {\n  std::cout << \"SSE4.1 not available, skipping benchmarks.\" << std::endl;\n  return 0;\n}\n\n#endif // defined(__SSE4_1__)\n"
  },
  {
    "path": "benchmarks/for_each_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Benchmarks for dispenso::for_each_n / dispenso::for_each.\n * Tests scheduling overhead across different container/iterator types:\n *   - vector (random-access)\n *   - deque (random-access)\n *   - list (bidirectional)\n *   - set (bidirectional, const elements)\n */\n\n#include <dispenso/for_each.h>\n\n#include <deque>\n#include <list>\n#include <set>\n#include <unordered_map>\n\n#include \"thread_benchmark_common.h\"\n\nstatic uint32_t kSeed(8);\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 1000000;\nstatic constexpr int kLargeSize = 100000000;\n\nconst std::vector<int>& getInputs(int num_elements) {\n  static std::unordered_map<int, std::vector<int>> vecs;\n  auto it = vecs.find(num_elements);\n  if (it != vecs.end()) {\n    return it->second;\n  }\n  srand(kSeed);\n  std::vector<int> values;\n  values.reserve(num_elements);\n  for (int i = 0; i < num_elements; ++i) {\n    values.push_back((rand() & 255) - 127);\n  }\n  auto res = vecs.emplace(num_elements, std::move(values));\n  assert(res.second);\n  return res.first->second;\n}\n\nvoid checkResults(const std::vector<int>& input, const std::vector<int>& output) {\n  for (size_t i = 0; i < input.size(); ++i) {\n    if (output[i] != input[i] * input[i] - 3 * input[i]) {\n      std::cerr << \"FAIL! \" << output[i] << \" vs \" << input[i] * input[i] - 3 * input[i]\n                << std::endl;\n      abort();\n    }\n  }\n}\n\ntemplate <int num_elements>\nvoid BM_serial(benchmark::State& state) {\n  std::vector<int> output(num_elements, 0);\n  auto& input = getInputs(num_elements);\n\n  for (auto UNUSED_VAR : state) {\n    for (size_t i = 0; i < num_elements; ++i) {\n      output[i] = input[i] * input[i] - 3 * input[i];\n    }\n  }\n}\n\nvoid BM_for_each_n(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  dispenso::ThreadPool pool(num_threads);\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    dispenso::for_each_n(\n        tasks, input.begin(), static_cast<size_t>(num_elements), [&output, &input](const int& val) {\n          size_t idx = static_cast<size_t>(&val - input.data());\n          output[idx] = val * val - 3 * val;\n        });\n  }\n  checkResults(input, output);\n}\n\nvoid BM_for_each_n_deque(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  auto& input = getInputs(num_elements);\n  std::deque<int> deq(input.begin(), input.end());\n  dispenso::ThreadPool pool(num_threads);\n\n  std::atomic<int64_t> sum(0);\n  for (auto UNUSED_VAR : state) {\n    sum.store(0, std::memory_order_relaxed);\n    dispenso::TaskSet tasks(pool);\n    dispenso::for_each_n(\n        tasks, deq.begin(), static_cast<size_t>(num_elements), [&sum](const int& val) {\n          sum.fetch_add(val * val - 3 * val, std::memory_order_relaxed);\n        });\n  }\n  benchmark::DoNotOptimize(sum.load());\n}\n\nvoid BM_for_each_n_list(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  auto& input = getInputs(num_elements);\n  std::list<int> lst(input.begin(), input.end());\n  dispenso::ThreadPool pool(num_threads);\n\n  std::atomic<int64_t> sum(0);\n  for (auto UNUSED_VAR : state) {\n    sum.store(0, std::memory_order_relaxed);\n    dispenso::TaskSet tasks(pool);\n    dispenso::for_each_n(\n        tasks, lst.begin(), static_cast<size_t>(num_elements), [&sum](const int& val) {\n          sum.fetch_add(val * val - 3 * val, std::memory_order_relaxed);\n        });\n  }\n  benchmark::DoNotOptimize(sum.load());\n}\n\nvoid BM_for_each_n_set(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  auto& input = getInputs(num_elements);\n  std::set<int> s(input.begin(), input.end());\n  // set deduplicates, so actual size may be smaller\n  size_t actual_size = s.size();\n  dispenso::ThreadPool pool(num_threads);\n\n  std::atomic<int64_t> sum(0);\n  for (auto UNUSED_VAR : state) {\n    sum.store(0, std::memory_order_relaxed);\n    dispenso::TaskSet tasks(pool);\n    dispenso::for_each_n(tasks, s.begin(), actual_size, [&sum](const int& val) {\n      sum.fetch_add(val * val - 3 * val, std::memory_order_relaxed);\n    });\n  }\n  benchmark::DoNotOptimize(sum.load());\n}\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\n// Smaller argument set for containers where 100M elements is impractical\nstatic void SmallArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\nBENCHMARK(BM_for_each_n)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_for_each_n_deque)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_for_each_n_list)->Apply(SmallArguments)->UseRealTime();\nBENCHMARK(BM_for_each_n_set)->Apply(SmallArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/for_latency_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/parallel_for.h>\n#include <dispenso/thread_pool.h>\n#include <dispenso/timing.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#include <random>\n#include <unordered_map>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_for.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nnamespace {\n\nusing namespace std::chrono_literals;\n\nuint32_t kSeed(8);\nconstexpr int kSize = 50000;\nconstexpr auto kSleep = 30ms;\n} // namespace\n\n// Adapted from Google gtest examples\n// Returns true iff n is a prime number.\nbool isPrime(int n) {\n  // Trivial case 1: small numbers\n  if (n <= 1)\n    return false;\n\n  // Trivial case 2: even numbers\n  if (n % 2 == 0)\n    return n == 2;\n\n  // Now, we have that n is odd and n >= 3.\n\n  // Try to divide n by every odd number i, starting from 3\n  for (int i = 3;; i += 2) {\n    // We only have to try i up to the squre root of n\n    if (i > n / i)\n      break;\n\n    // Now, we have i <= n/i < n.\n    // If n is divisible by i, n is not prime.\n    if (n % i == 0)\n      return false;\n  }\n\n  // n has no integer factor in the range (1, n), and thus is prime.\n  return true;\n}\n\nconst std::vector<int>& getInputs(int numElements) {\n  static std::unordered_map<int, std::vector<int>> vecs;\n  auto it = vecs.find(numElements);\n  if (it != vecs.end()) {\n    return it->second;\n  }\n\n  std::mt19937_64 gen64(kSeed);\n  std::uniform_int_distribution<> distribution(100000, 1000000);\n  std::vector<int> values;\n  values.reserve(numElements);\n  for (int i = 0; i < numElements; ++i) {\n    values.push_back(distribution(gen64));\n  }\n  auto res = vecs.emplace(numElements, std::move(values));\n  assert(res.second);\n  return res.first->second;\n}\n\nvoid BM_serial(benchmark::State& state) {\n  std::vector<int> output(kSize, 0);\n  auto& input = getInputs(kSize);\n\n  std::vector<double> times;\n  times.reserve(1000);\n\n  for (auto UNUSED_VAR : state) {\n    std::this_thread::sleep_for(kSleep);\n    times.push_back(dispenso::getTime());\n    for (size_t i = 0; i < kSize; ++i) {\n      output[i] = isPrime(input[i]);\n    }\n    times.back() = dispenso::getTime() - times.back();\n  }\n\n  doStats(times, state);\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int numThreads = state.range(0) - 1;\n\n  std::vector<int> output(kSize, 0);\n  dispenso::resizeGlobalThreadPool(numThreads);\n\n  std::vector<double> times;\n  times.reserve(1000);\n\n  auto& input = getInputs(kSize);\n  for (auto UNUSED_VAR : state) {\n    std::this_thread::sleep_for(kSleep);\n    times.push_back(dispenso::getTime());\n    dispenso::parallel_for(\n        dispenso::makeChunkedRange(0, kSize), [&input, &output](size_t i, size_t e) {\n          for (; i != e; ++i) {\n            output[i] = isPrime(input[i]);\n          }\n        });\n    times.back() = dispenso::getTime() - times.back();\n  }\n\n  doStats(times, state);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int numThreads = state.range(0);\n\n  std::vector<int> output(kSize, 0);\n  omp_set_num_threads(numThreads);\n\n  std::vector<double> times;\n  times.reserve(1000);\n\n  auto& input = getInputs(kSize);\n  for (auto UNUSED_VAR : state) {\n    std::this_thread::sleep_for(kSleep);\n    times.push_back(dispenso::getTime());\n#pragma omp parallel for\n    for (int i = 0; i < kSize; ++i) {\n      output[i] = isPrime(input[i]);\n    }\n    times.back() = dispenso::getTime() - times.back();\n  }\n  doStats(times, state);\n}\n#endif /*defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int numThreads = state.range(0);\n\n  std::vector<int> output(kSize, 0);\n\n  tbb_compat::task_scheduler_init initsched(numThreads);\n\n  std::vector<double> times;\n  times.reserve(1000);\n\n  auto& input = getInputs(kSize);\n  for (auto UNUSED_VAR : state) {\n    std::this_thread::sleep_for(kSleep);\n    times.push_back(dispenso::getTime());\n    tbb::parallel_for(\n        tbb::blocked_range<size_t>(0, kSize),\n        [&input, &output](const tbb::blocked_range<size_t>& r) {\n          for (size_t i = r.begin(); i < r.end(); ++i) {\n            output[i] = isPrime(input[i]);\n          }\n        });\n    times.back() = dispenso::getTime() - times.back();\n  }\n  doStats(times, state);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int i : pow2HalfStepThreads()) {\n    b->Arg(i);\n  }\n}\n\nBENCHMARK(BM_serial)->UseRealTime();\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif // OPENMP\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/future_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <array>\n#include <cmath>\n#include <future>\n#include <iostream>\n#include <random>\n\n#include <dispenso/future.h>\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\n#include <folly/executors/CPUThreadPoolExecutor.h>\n#include <folly/futures/Future.h>\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\n#include \"thread_benchmark_common.h\"\n\nconstexpr size_t kSmallSize = 13;\nconstexpr size_t kMediumSize = 16;\nconstexpr size_t kLargeSize = 19;\n\n// Note that there are many optimizations that could be made for these tree build routines.  The\n// goal was to make these as apples-to-apples as possible.\n\nstruct Node {\n  Node* left;\n  Node* right;\n  uint32_t value;\n\n  void setValue(uint32_t unique_bitset, uint32_t modulo) {\n    value = 0;\n    for (uint32_t i = 0; i < 32; ++i) {\n      value += unique_bitset % modulo;\n      unique_bitset /= modulo;\n    }\n  }\n};\n\nclass Allocator {\n public:\n  void reset(size_t depth) {\n    nodes_.resize(std::pow(2, depth) - 1);\n    next_.store(0, std::memory_order_release);\n  }\n\n  Node* alloc() {\n    size_t cur = next_.fetch_add(1, std::memory_order_relaxed);\n    return &nodes_[cur];\n  }\n\n private:\n  std::vector<Node> nodes_;\n  std::atomic<size_t> next_{0};\n};\n\nconst std::vector<uint32_t>& getModulos() {\n  static const std::vector<uint32_t> modulos = []() {\n    std::mt19937 mt;\n    std::uniform_int_distribution<> dis(2, 55);\n    std::vector<uint32_t> m;\n    for (size_t i = 0; i < 64; ++i) {\n      m.emplace_back(dis(mt));\n    }\n    return m;\n  }();\n  return modulos;\n}\n\nuint64_t sumTree(Node* root) {\n  if (!root) {\n    return 0;\n  }\n  return root->value + sumTree(root->left) + sumTree(root->right);\n}\n\nvoid checkTree(Node* root, uint32_t depth, uint32_t modulo) {\n  uint64_t expectedSum = 0;\n\n  uint32_t num = std::pow(2, depth);\n  for (uint32_t i = 0; i < num; ++i) {\n    auto bitset = i;\n    while (bitset) {\n      expectedSum += bitset % modulo;\n      bitset /= modulo;\n    }\n  }\n\n  uint64_t actual = sumTree(root);\n  if (actual != expectedSum) {\n    std::cerr << \"Mismatch! \" << expectedSum << \" vs \" << actual << std::endl;\n    std::abort();\n  }\n}\n\nNode* serialTree(Allocator& allocator, uint32_t depth, uint32_t bitset, uint32_t modulo) {\n  --depth;\n  Node* node = allocator.alloc();\n  node->setValue(bitset, modulo);\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return node;\n  }\n  node->left = serialTree(allocator, depth, (bitset << 1), modulo);\n  node->right = serialTree(allocator, depth, (bitset << 1) | 1, modulo);\n\n  return node;\n}\n\ntemplate <size_t depth>\nvoid BM_serial_tree(benchmark::State& state) {\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n\n  uint32_t modulo;\n\n  Node* root;\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    root = serialTree(alloc, depth, 1, modulo);\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(root, depth, modulo);\n}\n\nNode* stdTree(Allocator& allocator, uint32_t depth, uint32_t bitset, uint32_t modulo) {\n  --depth;\n  Node* node = allocator.alloc();\n  node->setValue(bitset, modulo);\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return node;\n  }\n  auto left = std::async([&]() { return stdTree(allocator, depth, (bitset << 1), modulo); });\n  auto right = std::async([&]() { return stdTree(allocator, depth, (bitset << 1) | 1, modulo); });\n  node->left = left.get();\n  node->right = right.get();\n\n  return node;\n}\n\ntemplate <size_t depth>\nvoid BM_std_tree(benchmark::State& state) {\n#if defined(__APPLE__) || defined(__ANDROID__)\n  // std::async on macOS and Android (libc++) creates a real thread per call.\n  // At depth 16+ this spawns tens of thousands of threads recursively,\n  // exhausting OS thread limits and hanging the process.\n  if (depth >= kMediumSize) {\n    state.SkipWithError(\"std::async hangs on this platform at this tree depth\");\n    return;\n  }\n#elif defined(_WIN32)\n  // std::async on Windows uses a threadpool. The recursive tree construction\n  // pattern causes deadlock as threadpool threads wait for tasks that require\n  // more threadpool threads. Skip all depths on Windows.\n  state.SkipWithError(\"std::async deadlocks on Windows threadpool\");\n  return;\n#endif\n\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n\n  uint32_t modulo;\n\n  Node* root;\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    root = stdTree(alloc, depth, 1, modulo);\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(root, depth, modulo);\n}\n\nNode* dispensoTree(Allocator& allocator, uint32_t depth, uint32_t bitset, uint32_t modulo) {\n  --depth;\n  Node* node = allocator.alloc();\n  node->setValue(bitset, modulo);\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return node;\n  }\n\n  auto left = dispenso::async(\n      [=, &allocator]() { return dispensoTree(allocator, depth, (bitset << 1), modulo); });\n  auto right = dispenso::async(\n      [=, &allocator]() { return dispensoTree(allocator, depth, (bitset << 1) | 1, modulo); });\n  node->left = left.get();\n  node->right = right.get();\n\n  return node;\n}\n\ntemplate <size_t depth>\nvoid BM_dispenso_tree(benchmark::State& state) {\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n  dispenso::globalThreadPool();\n\n  uint32_t modulo;\n\n  Node* root;\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    root = dispensoTree(alloc, depth, 1, modulo);\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(root, depth, modulo);\n}\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nfolly::SemiFuture<folly::Unit> follyTree(\n    folly::Executor* exec,\n    Node* node,\n    Allocator* allocator,\n    uint32_t depth,\n    uint32_t bitset,\n    uint32_t modulo) {\n  --depth;\n  node->setValue(bitset, modulo);\n\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return folly::Unit{};\n  }\n\n  node->left = allocator->alloc();\n  node->right = allocator->alloc();\n\n  return folly::via(\n             exec,\n             [=]() {\n               return folly::collectAll(\n                          follyTree(exec, node->left, allocator, depth, bitset << 1, modulo),\n                          follyTree(exec, node->right, allocator, depth, bitset << 1 | 1, modulo))\n                   .unit();\n             })\n      .semi();\n}\n\ntemplate <size_t depth>\nvoid BM_folly_tree(benchmark::State& state) {\n  folly::CPUThreadPoolExecutor follyExec{std::thread::hardware_concurrency()};\n  Allocator alloc;\n  alloc.reset(depth);\n\n  uint32_t modulo;\n\n  Node root;\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    follyTree(&follyExec, &root, &alloc, depth, 1, modulo).via(&follyExec).get();\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n  checkTree(&root, depth, modulo);\n}\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nvoid dispensoTaskSetTree(\n    dispenso::ConcurrentTaskSet& tasks,\n    Node* node,\n    Allocator& allocator,\n    uint32_t depth,\n    uint32_t bitset,\n    uint32_t modulo) {\n  node->setValue(bitset, modulo);\n  --depth;\n\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return;\n  }\n\n  tasks.schedule(\n      [&tasks, &allocator, node, depth, bitset, modulo]() {\n        node->left = allocator.alloc();\n        dispensoTaskSetTree(tasks, node->left, allocator, depth, (bitset << 1), modulo);\n      },\n      true);\n  tasks.schedule(\n      [&tasks, &allocator, node, depth, bitset, modulo]() {\n        node->right = allocator.alloc();\n        dispensoTaskSetTree(tasks, node->right, allocator, depth, (bitset << 1) | 1, modulo);\n      },\n      true);\n}\n\ntemplate <size_t depth>\nvoid BM_dispenso_taskset_tree(benchmark::State& state) {\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n\n  uint32_t modulo;\n  Node root;\n\n  dispenso::ConcurrentTaskSet tasks(\n      dispenso::globalThreadPool(), dispenso::ParentCascadeCancel::kOff, 2);\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    dispensoTaskSetTree(tasks, &root, alloc, depth, 1, modulo);\n    tasks.wait();\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(&root, depth, modulo);\n}\n\nvoid dispensoTaskSetTreeBulk(\n    dispenso::ConcurrentTaskSet& tasks,\n    Node* node,\n    Allocator& allocator,\n    uint32_t depth,\n    uint32_t bitset,\n    uint32_t modulo) {\n  node->setValue(bitset, modulo);\n  --depth;\n\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return;\n  }\n\n  std::array<Node**, 2> children = {&node->left, &node->right};\n  tasks.scheduleBulk(2, [&tasks, &allocator, children, depth, bitset, modulo](size_t i) {\n    return [&tasks,\n            &allocator,\n            child = children[i],\n            depth,\n            bitset = (bitset << 1) | static_cast<uint32_t>(i),\n            modulo]() {\n      *child = allocator.alloc();\n      dispensoTaskSetTreeBulk(tasks, *child, allocator, depth, bitset, modulo);\n    };\n  });\n}\n\ntemplate <size_t depth>\nvoid BM_dispenso_taskset_tree_bulk(benchmark::State& state) {\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n\n  uint32_t modulo;\n  Node root;\n\n  dispenso::ConcurrentTaskSet tasks(\n      dispenso::globalThreadPool(), dispenso::ParentCascadeCancel::kOff, 2);\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    dispensoTaskSetTreeBulk(tasks, &root, alloc, depth, 1, modulo);\n    tasks.wait();\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(&root, depth, modulo);\n}\n\ndispenso::Future<Node*>\ndispensoTreeWhenAll(Allocator& allocator, uint32_t depth, uint32_t bitset, uint32_t modulo) {\n  --depth;\n  Node* node = allocator.alloc();\n  node->setValue(bitset, modulo);\n  if (!depth) {\n    node->left = nullptr;\n    node->right = nullptr;\n    return dispenso::make_ready_future(node);\n  }\n\n  auto left = dispenso::async([depth, bitset, modulo, &allocator]() {\n    return dispensoTreeWhenAll(allocator, depth, (bitset << 1), modulo);\n  });\n  auto right = dispenso::async([depth, bitset, modulo, &allocator]() {\n    return dispensoTreeWhenAll(allocator, depth, (bitset << 1) | 1, modulo);\n  });\n  return dispenso::when_all(left, right).then([node](auto&& both) {\n    auto& tuple = both.get();\n    node->left = std::get<0>(tuple).get().get();\n    node->right = std::get<1>(tuple).get().get();\n    return node;\n  });\n}\n\ntemplate <size_t depth>\nvoid BM_dispenso_tree_when_all(benchmark::State& state) {\n  Allocator alloc;\n  alloc.reset(depth);\n  getModulos();\n  dispenso::globalThreadPool();\n\n  uint32_t modulo;\n\n  Node* root;\n\n  size_t m = 0;\n\n  for (auto UNUSED_VAR : state) {\n    alloc.reset(depth);\n    modulo = getModulos()[m];\n    root = dispensoTreeWhenAll(alloc, depth, 1, modulo).get();\n    m = (m + 1 == getModulos().size()) ? 0 : m + 1;\n  }\n\n  checkTree(root, depth, modulo);\n}\n\nBENCHMARK_TEMPLATE(BM_serial_tree, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_serial_tree, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_serial_tree, kLargeSize)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_std_tree, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_std_tree, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_std_tree, kLargeSize)->UseRealTime();\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nBENCHMARK_TEMPLATE(BM_folly_tree, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_folly_tree, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_folly_tree, kLargeSize)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nBENCHMARK_TEMPLATE(BM_dispenso_tree, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_tree, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_tree, kLargeSize)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree, kLargeSize)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree_bulk, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree_bulk, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_taskset_tree_bulk, kLargeSize)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_dispenso_tree_when_all, kSmallSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_tree_when_all, kMediumSize)->UseRealTime();\nBENCHMARK_TEMPLATE(BM_dispenso_tree_when_all, kLargeSize)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/graph_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <benchmark/benchmark.h>\n#include <taskflow/taskflow.hpp>\n#include <array>\n#include <numeric>\n#include <random>\n\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n\n//--------------------------------------------------------------------------------\n//                                    Taskflow\n//--------------------------------------------------------------------------------\nclass TaskFlowBigTree {\n public:\n  static size_t sizeOfLevel(size_t level) {\n    return 1ul << (numBits_ - shiftStep_ * level);\n  }\n  void buildTree() {\n    for (size_t level = 1; level < numLevels_; ++level) {\n      buildLevel(level);\n    }\n  }\n\n  void allocateMemory() {\n    // the goal of this task is to calculate the sum of the numbers in this array\n    for (size_t level = 1; level < numLevels_; ++level) {\n      const size_t s = sizeOfLevel(level);\n      data_[level].resize(s, 0lu);\n    }\n\n    // zero level data is input data for calculation\n    data_[0].resize(1ul << numBits_);\n    std::iota(data_[0].begin(), data_[0].end(), 0);\n  }\n  void initData() {\n    for (size_t level = 1; level < numLevels_; ++level) {\n      std::fill(data_[level].begin(), data_[level].end(), 0.f);\n    }\n    std::iota(data_[0].begin(), data_[0].end(), 0);\n  }\n\n  void buildLevel(size_t level) {\n    std::vector<tf::Task>& tasks = levelTasks_[level];\n\n    const size_t numNodes = 1ul << (numBits_ - shiftStep_ * level);\n\n    for (size_t n = 0; n < numNodes; ++n) {\n      tasks.push_back(taskflow_.emplace([this, level, n]() {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          data_[level][n] += data_[level - 1][index];\n        }\n      }));\n      if (level > 1) {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          levelTasks_[level][n].succeed(levelTasks_[level - 1][index]);\n        }\n      }\n    }\n  }\n\n  bool testTree() {\n    const size_t result = std::accumulate(this->data_[0].begin(), this->data_[0].end(), size_t(0));\n    executor_.run(taskflow_).wait();\n    const bool isTestPass = data_[numLevels_ - 1][0] == result;\n    initData();\n    return isTestPass;\n  }\n  static constexpr size_t shiftStep_ = 4; // 4\n  static constexpr size_t numBits_ = 5 * shiftStep_; // 5 // should be divisible by shiftStep\n  static constexpr size_t numPredecessors_ = 1 << shiftStep_;\n  static constexpr size_t startShnft_ = shiftStep_;\n  static constexpr size_t numLevels_ = numBits_ / shiftStep_ + 1;\n  static constexpr size_t level0Size_ = 1ul << numBits_;\n\n  std::array<std::vector<size_t>, numLevels_> data_;\n  std::array<std::vector<tf::Task>, numLevels_> levelTasks_;\n  tf::Taskflow taskflow_;\n  tf::Executor executor_;\n};\n//--------------------------------------------------------------------------------\n//                                dispenso::Graph\n//--------------------------------------------------------------------------------\ntemplate <class G>\nclass BigTree {\n public:\n  static size_t sizeOfLevel(size_t level) {\n    return 1ul << (numBits_ - shiftStep_ * level);\n  }\n  void buildTree() {\n    for (size_t level = 1; level < numLevels_; ++level) {\n      subgraphs_[level] = &g_.addSubgraph();\n      buildLevel(level);\n    }\n  }\n\n  void allocateMemory() {\n    // the goal of this task is to calculate the sum of the numbers in this array\n    for (size_t level = 1; level < numLevels_; ++level) {\n      const size_t s = sizeOfLevel(level);\n      data_[level].resize(s, 0lu);\n    }\n\n    // zero level data is input data for calculation\n    data_[0].resize(1ul << numBits_);\n    std::iota(data_[0].begin(), data_[0].end(), 0);\n  }\n\n  void initData() {\n    for (size_t level = 1; level < numLevels_; ++level) {\n      std::fill(data_[level].begin(), data_[level].end(), 0.f);\n    }\n    std::iota(data_[0].begin(), data_[0].end(), 0);\n  }\n\n  void buildLevel(size_t level) {\n    SubGraphType* subgraph = subgraphs_[level];\n\n    const size_t numNodes = 1ul << (numBits_ - shiftStep_ * level);\n    subgraph->reserve(numNodes);\n\n    for (size_t n = 0; n < numNodes; ++n) {\n      subgraph->addNode([this, level, n]() {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          data_[level][n] += data_[level - 1][index];\n        }\n      });\n      if (level > 1) {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          subgraphs_[level]->node(n).dependsOn(subgraphs_[level - 1]->node(index));\n        }\n      }\n    }\n  }\n\n  bool testTree() {\n    const size_t result = std::accumulate(this->data_[0].begin(), this->data_[0].end(), size_t(0));\n\n    dispenso::ThreadPool& threadPool = dispenso::globalThreadPool();\n    dispenso::ConcurrentTaskSet concurrentTaskSet(threadPool);\n    setAllNodesIncomplete(g_);\n    executor_(concurrentTaskSet, g_);\n    concurrentTaskSet.wait();\n\n    const bool isTestPass = data_[numLevels_ - 1][0] == result;\n    initData();\n    return isTestPass;\n  }\n  static constexpr size_t shiftStep_ = 4; // 4\n  static constexpr size_t numBits_ = 5 * shiftStep_; // 5 // should be divisible by shiftStep\n  static constexpr size_t numPredecessors_ = 1 << shiftStep_;\n  static constexpr size_t startShnft_ = shiftStep_;\n  static constexpr size_t numLevels_ = numBits_ / shiftStep_ + 1;\n  static constexpr size_t level0Size_ = 1ul << numBits_;\n\n  using SubGraphType = typename G::SubgraphType;\n\n  std::array<std::vector<size_t>, numLevels_> data_;\n  std::array<SubGraphType*, numLevels_> subgraphs_;\n  G g_;\n  dispenso::ConcurrentTaskSetExecutor executor_;\n};\n\nstatic void BM_taskflow_build_big_tree(benchmark::State& state) {\n  TaskFlowBigTree bigTree;\n  bigTree.allocateMemory();\n  for (auto _ : state) {\n    bigTree.buildTree();\n    assert(bigTree.testTree());\n    bigTree.taskflow_.clear();\n    for (uint32_t i = 0; i < TaskFlowBigTree::numLevels_; ++i) {\n      bigTree.levelTasks_[i].clear();\n    }\n  }\n}\n\ntemplate <class G>\nstatic void BM_build_big_tree(benchmark::State& state) {\n  BigTree<G> bigTree;\n  bigTree.allocateMemory();\n  for (auto _ : state) {\n    bigTree.buildTree();\n    assert(bigTree.testTree());\n    bigTree.g_.clear();\n  }\n}\n\nstatic void BM_build_bi_prop_dependency_chain(benchmark::State& state) {\n  size_t counter;\n  for (auto _ : state) {\n    dispenso::BiPropGraph graph;\n    dispenso::BiPropNode* prevNode = &graph.addNode([&counter]() { counter++; });\n    for (size_t i = 1; i < 1024; ++i) {\n      dispenso::BiPropNode* node = &graph.addNode([&counter]() { counter++; });\n      prevNode->biPropDependsOn(*node);\n      prevNode = node;\n    }\n  }\n}\n\ntemplate <class G>\nstatic void BM_build_dependency_chain(benchmark::State& state) {\n  size_t counter;\n  for (auto _ : state) {\n    G graph;\n    typename G::NodeType* prevNode = &graph.addNode([&counter]() { counter++; });\n    for (size_t i = 1; i < 1024; ++i) {\n      typename G::NodeType* node = &graph.addNode([&counter]() { counter++; });\n      prevNode->dependsOn(*node);\n      prevNode = node;\n    }\n  }\n}\n\ntemplate <class G>\nstatic void BM_execute_dependency_chain(benchmark::State& state) {\n  size_t counter;\n  G graph;\n  typename G::NodeType* prevNode = &graph.addNode([&counter]() { counter++; });\n  for (size_t i = 1; i < 1024; ++i) {\n    typename G::NodeType* node = &graph.addNode([&counter]() { counter++; });\n    prevNode->dependsOn(*node);\n    prevNode = node;\n  }\n\n  dispenso::SingleThreadExecutor singleThreadExecutor;\n  for (auto _ : state) {\n    setAllNodesIncomplete(graph);\n    counter = 0;\n    singleThreadExecutor(graph);\n  }\n}\n\nstatic void BM_build_bi_prop_dependency_group(benchmark::State& state) {\n  size_t counter;\n  constexpr size_t numNodes = 4;\n  std::array<dispenso::BiPropNode*, numNodes> nodes1, nodes2;\n  for (auto _ : state) {\n    dispenso::BiPropGraph graph;\n    for (size_t i = 0; i < numNodes; ++i) {\n      nodes1[i] = &graph.addNode([&counter]() { counter++; });\n      nodes2[i] = &graph.addNode([&counter]() { counter++; });\n      nodes1[i]->biPropDependsOn(*nodes2[i]);\n    }\n    for (size_t i = 1; i < numNodes; ++i) {\n      nodes1[i - 1]->biPropDependsOn(*nodes1[i]);\n    }\n  }\n}\n\ntemplate <class G>\nstatic void BM_forward_propagator_node(benchmark::State& state) {\n  G graph;\n  constexpr size_t numNodes = 32768;\n  std::array<dispenso::Node*, numNodes> nodes;\n\n  size_t counter;\n\n  std::mt19937 rng(12345);\n\n  nodes[0] = &graph.addNode([&counter]() { counter++; }); // root\n  for (size_t i = 1; i < numNodes; ++i) {\n    nodes[i] = &graph.addNode([&counter]() { counter++; });\n    std::uniform_int_distribution<> parentDistr(0, i - 1);\n    nodes[i]->dependsOn(*nodes[parentDistr(rng)]);\n  }\n\n  dispenso::ForwardPropagator forwardPropagator;\n\n  for (auto _ : state) {\n    state.PauseTiming();\n    graph.forEachNode([](const dispenso::Node& node) { node.setCompleted(); });\n\n    nodes[0]->setIncomplete();\n    state.ResumeTiming();\n    forwardPropagator(graph);\n  }\n}\n\nBENCHMARK(BM_taskflow_build_big_tree);\nBENCHMARK_TEMPLATE(BM_build_big_tree, dispenso::Graph);\nBENCHMARK_TEMPLATE(BM_build_big_tree, dispenso::BiPropGraph);\nBENCHMARK(BM_build_bi_prop_dependency_chain);\nBENCHMARK(BM_build_bi_prop_dependency_group);\nBENCHMARK_TEMPLATE(BM_build_dependency_chain, dispenso::Graph);\nBENCHMARK_TEMPLATE(BM_build_dependency_chain, dispenso::BiPropGraph);\nBENCHMARK_TEMPLATE(BM_execute_dependency_chain, dispenso::Graph);\nBENCHMARK_TEMPLATE(BM_execute_dependency_chain, dispenso::BiPropGraph);\nBENCHMARK_TEMPLATE(BM_forward_propagator_node, dispenso::Graph);\nBENCHMARK_TEMPLATE(BM_forward_propagator_node, dispenso::BiPropGraph);\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/graph_scene_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <benchmark/benchmark.h>\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n#include <taskflow/taskflow.hpp>\n#if TF_VERSION > 300000\n#include <taskflow/algorithm/for_each.hpp>\n#endif // TF_VERSION\n#include <array>\n#include <numeric>\n#include <random>\n// For this benchmarks we create set of tasks similar to the scene graph.\n// Scene consist of the hierarchy of the Transforms which have local space transformation matrix.\n// World matrix should be calculated as multiplication of the parent world matrix and local space\n// matrix of the transform. Some transforms have two geometry index. inGeoIdex - is index in source\n// geometry array (which generated by functions). This geometry should be transformed by worldMatrix\n// and stored into outGeo array.\n//                                                    generateGeo─┐\n//                                                                │\n//                                                             4  │\n//     transform 2 ◀──────┐   transform 5                ┌─   ─┬──▼─────┬─   ─┐\n//    ┌─────────────┐     │  ┌───────────────┐   inGeo:  │ ... │ points │ ... │\n//    │ parent      │     └────parent       2│           └─   ─┴──┬─────┴─   ─┘\n//    │ matrix      │   ┌──◀───matrix        │                    │\n//    │ worldMatrix─────*────▶ worldMatrix   │───────▶────────────* transformGeo\n//    │ inGeoIndex  │        │ inGeoIndex   4│                  9 │\n//    │ outGeoIndex │        │ outGeoIndex  9│           ┌──  ─┬──▼─────┬─   ─┐\n//    └─────────────┘        └───────────────┘   outGeo: │ ... │ points │ ... │\n//             calculateWorldMatrix                      └──  ─┴────────┴─   ─┘\n\nnamespace {\nnamespace params {\n// parameters of the scene\nconstexpr size_t numTransforms = 1000; // number transforms in hierarchy\nconstexpr size_t numInGeo = 100; // number unique geometries\nconstexpr size_t numVertexMultiplier = 1024;\nconstexpr size_t everyNthHasGeo = 2; // probability that transform has geo is 1/everyNthHasGeo\n} // namespace params\n\nusing Vec3 = std::array<float, 3>;\nusing Matrix4 = std::array<float, 16>;\n\nconstexpr size_t kNoGeometry = std::numeric_limits<size_t>::max();\nconstexpr float kPi = 3.14159265358979323846f;\nconstexpr size_t kRoot = std::numeric_limits<size_t>::max();\nstruct Transform {\n  Matrix4 matrix;\n  Matrix4 worldMatrix;\n  size_t parent = kRoot;\n  size_t inGeoIndex = kNoGeometry;\n  size_t outGeoIndex = kNoGeometry;\n};\n\nusing Geometry = std::vector<Vec3>;\n\nstruct Scene {\n  std::vector<Transform> transforms;\n  std::vector<Geometry> inGeo;\n  std::vector<Geometry> outGeo;\n};\n//--------------------------------------------------------------------------------\nvoid branchlessONB(const Vec3& n, Vec3& b1, Vec3& b2) {\n  const float sign = std::copysign(1.f, n[2]);\n  const float a = -1.0f / (sign + n[2]);\n  const float b = n[0] * n[1] * a;\n  b1 = Vec3{1.0f + sign * n[0] * n[0] * a, sign * b, -sign * n[0]};\n  b2 = Vec3{b, sign + n[1] * n[1] * a, -n[1]};\n}\n\nMatrix4 getRandomTransformMatrix(std::mt19937& rng) {\n  std::uniform_real_distribution<float> thetaDistr(0.f, 2.f * kPi);\n  std::uniform_real_distribution<float> uDistr(-1.f, 1.f);\n  const float theta = thetaDistr(rng);\n  const float u = uDistr(rng);\n  const float sq = std::sqrt(1 - u * u);\n  const Vec3 dirY = {sq * std::cos(theta), sq * std::sin(theta), u};\n  Vec3 dirX, dirZ;\n  branchlessONB(dirY, dirZ, dirX);\n  const Vec3 pos{uDistr(rng), uDistr(rng), uDistr(rng)};\n  // clang-format off\n  return {dirX[0], dirX[1], dirX[2], 0.f,\n          dirY[0], dirY[1], dirY[2], 0.f,\n          dirZ[0], dirZ[1], dirZ[2], 0.f,\n          pos[0],  pos[1],  pos[2],  1.f };\n  // clang-format on\n}\n\nScene generateTransformsHierarchy(\n    size_t numTransforms,\n    size_t numInGeo,\n    size_t everyNthHasGeo,\n    std::mt19937& rng) {\n  std::uniform_int_distribution<size_t> distGeom(0, numInGeo - 1);\n  std::uniform_int_distribution<size_t> distProb(0, everyNthHasGeo - 1);\n\n  Scene scene;\n  scene.inGeo.resize(numInGeo);\n  std::vector<Transform>& transforms = scene.transforms;\n  transforms.resize(numTransforms);\n  transforms[0].matrix = getRandomTransformMatrix(rng);\n  transforms[0].worldMatrix = transforms[0].matrix;\n  size_t outGeoCounter = 0;\n  for (size_t i = 1; i < numTransforms; ++i) {\n    Transform& transform = transforms[i];\n    std::uniform_int_distribution<size_t> dist(0, i - 1);\n    transform.parent = dist(rng);\n    transform.matrix = getRandomTransformMatrix(rng);\n    if (distProb(rng) == 0) {\n      transform.inGeoIndex = distGeom(rng);\n      transform.outGeoIndex = outGeoCounter++;\n    }\n  }\n  scene.outGeo.resize(outGeoCounter);\n  return scene;\n}\n//--------------------------------compute functions-------------------------------\nVec3 multiply(const Vec3& v, const Matrix4& m) {\n  const float invertW = 1.f / (m[11] * v[2] + m[7] * v[1] + m[3] * v[0] + m[15]);\n  return {\n      (m[8] * v[2] + m[4] * v[1] + m[0] * v[0] + m[12]) * invertW,\n      (m[9] * v[2] + m[5] * v[1] + m[1] * v[0] + m[13]) * invertW,\n      (m[10] * v[2] + m[6] * v[1] + m[2] * v[0] + m[14]) * invertW};\n}\n\nMatrix4 multiply(const Matrix4& ma, const Matrix4& mb) {\n  return {\n      ma[2] * mb[8] + ma[1] * mb[4] + ma[3] * mb[12] + ma[0] * mb[0],\n      ma[2] * mb[9] + ma[1] * mb[5] + ma[3] * mb[13] + ma[0] * mb[1],\n      ma[1] * mb[6] + ma[0] * mb[2] + ma[3] * mb[14] + ma[2] * mb[10],\n      ma[1] * mb[7] + ma[0] * mb[3] + ma[3] * mb[15] + ma[2] * mb[11],\n      ma[6] * mb[8] + ma[5] * mb[4] + ma[7] * mb[12] + ma[4] * mb[0],\n      ma[6] * mb[9] + ma[5] * mb[5] + ma[7] * mb[13] + ma[4] * mb[1],\n      ma[5] * mb[6] + ma[4] * mb[2] + ma[7] * mb[14] + ma[6] * mb[10],\n      ma[5] * mb[7] + ma[4] * mb[3] + ma[7] * mb[15] + ma[6] * mb[11],\n      ma[10] * mb[8] + ma[9] * mb[4] + ma[11] * mb[12] + ma[8] * mb[0],\n      ma[10] * mb[9] + ma[9] * mb[5] + ma[11] * mb[13] + ma[8] * mb[1],\n      ma[9] * mb[6] + ma[8] * mb[2] + ma[11] * mb[14] + ma[10] * mb[10],\n      ma[9] * mb[7] + ma[8] * mb[3] + ma[11] * mb[15] + ma[10] * mb[11],\n      ma[14] * mb[8] + ma[13] * mb[4] + ma[15] * mb[12] + ma[12] * mb[0],\n      ma[14] * mb[9] + ma[13] * mb[5] + ma[15] * mb[13] + ma[12] * mb[1],\n      ma[13] * mb[6] + ma[12] * mb[2] + ma[15] * mb[14] + ma[14] * mb[10],\n      ma[13] * mb[7] + ma[12] * mb[3] + ma[15] * mb[15] + ma[14] * mb[11]};\n}\n\nvoid calculateWorldMatrix(std::vector<Transform>& transforms, size_t index) {\n  Transform& transform = transforms[index];\n  if (transform.parent == kRoot) {\n    transform.worldMatrix = transform.matrix;\n  } else {\n    transform.worldMatrix = multiply(transform.matrix, transforms[transform.parent].worldMatrix);\n  }\n}\n\nsize_t numGeoPoints(size_t inGeoIndex) {\n  return (inGeoIndex + 1) * params::numVertexMultiplier;\n}\n\nVec3 calculateGeoPoint(size_t inGeoIndex, size_t pointIndex) {\n  size_t numPoints = numGeoPoints(inGeoIndex);\n  const float tStep = 2.f * 2.f * kPi / (static_cast<float>(numPoints) - 1.f);\n  const float t = tStep * static_cast<float>(pointIndex);\n\n  const float r = 0.01;\n  return {r * t * std::cos(t), r * t * std::sin(t), r * (t + std::sin(16 * t))};\n}\n//--------------------------------------------------------------------------------\n//                                    taskflow\n//--------------------------------------------------------------------------------\ntf::Task generateGeoTF(tf::Taskflow& taskflow, std::vector<Geometry>& inGeo, size_t inGeoIndex) {\n  size_t numPoints = numGeoPoints(inGeoIndex);\n  Geometry& g = inGeo[inGeoIndex];\n  g.resize(numPoints);\n\n  return taskflow.for_each_index(\n      size_t(0), numPoints, size_t(1), [&](size_t i) { g[i] = calculateGeoPoint(inGeoIndex, i); });\n}\n\ntf::Task\ntransformGeoTF(tf::Taskflow& taskflow, Geometry& g, const Geometry& inG, const Matrix4& m) {\n  const size_t numPoints = inG.size();\n\n  g.resize(numPoints);\n\n  return taskflow.for_each_index(\n      size_t(0), numPoints, size_t(1), [&](size_t i) { g[i] = multiply(inG[i], m); });\n}\n\nvoid prepareGraphTF(tf::Taskflow& taskflow, Scene& scene) {\n  std::mt19937 rng(12345);\n\n  scene = generateTransformsHierarchy(\n      params::numTransforms, params::numInGeo, params::everyNthHasGeo, rng);\n\n  std::vector<Geometry>& inGeo = scene.inGeo;\n  std::vector<Transform>& transforms = scene.transforms;\n  std::vector<Geometry>& outGeo = scene.outGeo;\n  // calculate inGeo\n  std::vector<tf::Task> inGeoTasks(params::numInGeo);\n\n  for (size_t i = 0; i < params::numInGeo; ++i) {\n    inGeoTasks[i] = generateGeoTF(taskflow, inGeo, i);\n  }\n\n  // calculate transforms\n  std::vector<tf::Task> transformTasks(params::numTransforms);\n  std::vector<tf::Task> outGeoTasks(outGeo.size());\n  for (size_t i = 0; i < params::numTransforms; ++i) {\n    transformTasks[i] =\n        taskflow.emplace([&transforms, i]() { calculateWorldMatrix(transforms, i); });\n    const size_t parentIndex = transforms[i].parent;\n    if (parentIndex != kRoot) {\n      transformTasks[i].succeed(transformTasks[parentIndex]);\n    }\n\n    // calculate outGeo\n    const size_t outGeoIndex = transforms[i].outGeoIndex;\n    const size_t inGeoIndex = transforms[i].inGeoIndex;\n    if (inGeoIndex != kNoGeometry) {\n      outGeoTasks[outGeoIndex] = transformGeoTF(\n          taskflow, outGeo[outGeoIndex], inGeo[inGeoIndex], transforms[i].worldMatrix);\n\n      outGeoTasks[outGeoIndex].succeed(transformTasks[i], inGeoTasks[inGeoIndex]);\n    }\n  }\n}\n//--------------------------------------------------------------------------------\n//                                    dispenso\n//--------------------------------------------------------------------------------\nvoid generateGeo(\n    dispenso::ThreadPool& threadPool,\n    std::vector<Geometry>& inGeo,\n    size_t inGeoIndex) {\n  size_t numPoints = numGeoPoints(inGeoIndex);\n  Geometry& g = inGeo[inGeoIndex];\n  g.resize(numPoints);\n\n  dispenso::TaskSet taskSet(threadPool);\n\n  dispenso::ParForOptions options;\n  options.maxThreads = static_cast<uint32_t>(numPoints);\n  options.minItemsPerChunk = 256;\n\n  dispenso::parallel_for(\n      taskSet, 0, numPoints, [&](size_t i) { g[i] = calculateGeoPoint(inGeoIndex, i); }, options);\n}\n\nvoid transformGeo(\n    dispenso::ThreadPool& threadPool,\n    Geometry& g,\n    const Geometry& inG,\n    const Matrix4& m) {\n  dispenso::TaskSet taskSet(threadPool);\n  const size_t numPoints = inG.size();\n  dispenso::ParForOptions options;\n  options.maxThreads = static_cast<uint32_t>(numPoints);\n  options.minItemsPerChunk = 256;\n\n  g.resize(numPoints);\n\n  dispenso::parallel_for(\n      taskSet, 0, numPoints, [&](size_t i) { g[i] = multiply(inG[i], m); }, options);\n}\n\nstruct Subgraphs {\n  dispenso::Subgraph* inGeo;\n  dispenso::Subgraph* transforms;\n  dispenso::Subgraph* outGeo;\n};\nSubgraphs prepareGraph(dispenso::ThreadPool& threadPool, Scene& scene, dispenso::Graph& g) {\n  std::mt19937 rng(12345);\n\n  scene = generateTransformsHierarchy(\n      params::numTransforms, params::numInGeo, params::everyNthHasGeo, rng);\n\n  std::vector<Geometry>& inGeo = scene.inGeo;\n  std::vector<Transform>& transforms = scene.transforms;\n  std::vector<Geometry>& outGeo = scene.outGeo;\n  // calculate inGeo\n  dispenso::Subgraph& transformsSub = g.addSubgraph();\n  dispenso::Subgraph& inGeoSub = g.addSubgraph();\n  dispenso::Subgraph& outGeoSub = g.addSubgraph();\n\n  // Reserve capacity for known sizes\n  transformsSub.reserve(params::numTransforms);\n  inGeoSub.reserve(params::numInGeo);\n\n  for (size_t i = 0; i < params::numInGeo; ++i) {\n    inGeoSub.addNode([&threadPool, &inGeo, i]() { generateGeo(threadPool, inGeo, i); });\n  }\n\n  // calculate transforms\n  for (size_t i = 0; i < params::numTransforms; ++i) {\n    transformsSub.addNode([&transforms, i]() { calculateWorldMatrix(transforms, i); });\n    const size_t parentIndex = transforms[i].parent;\n    if (parentIndex != kRoot) {\n      transformsSub.node(i).dependsOn(transformsSub.node(parentIndex));\n    }\n\n    // calculate outGeo\n    const size_t outGeoIndex = transforms[i].outGeoIndex;\n    const size_t inGeoIndex = transforms[i].inGeoIndex;\n    if (inGeoIndex != kNoGeometry) {\n      outGeoSub.addNode([&, i, inGeoIndex, outGeoIndex]() {\n        transformGeo(threadPool, outGeo[outGeoIndex], inGeo[inGeoIndex], transforms[i].worldMatrix);\n      });\n      outGeoSub.node(outGeoIndex).dependsOn(transformsSub.node(i), inGeoSub.node(inGeoIndex));\n    }\n  }\n\n  return {&inGeoSub, &transformsSub, &outGeoSub};\n}\n\n//----------------------------------test results----------------------------------\n#ifndef NDEBUG\ntemplate <size_t N>\nbool compare(const std::array<float, N>& ma, const std::array<float, N>& mb) {\n  bool result = true;\n  for (size_t i = 0; i < N; ++i) {\n    result = result && std::abs(ma[i] - mb[i]) < std::numeric_limits<float>::epsilon();\n  }\n  return result;\n}\n\nbool testScene(const Scene& scene) {\n  bool result = true;\n  for (const Transform& transform : scene.transforms) {\n    const Matrix4 worldMatrix = transform.parent == kRoot\n        ? transform.matrix\n        : multiply(transform.matrix, scene.transforms[transform.parent].worldMatrix);\n    result = result && compare(transform.worldMatrix, worldMatrix);\n  }\n\n  for (const Transform& transform : scene.transforms) {\n    const size_t outGeoIndex = transform.outGeoIndex;\n    const size_t inGeoIndex = transform.inGeoIndex;\n    if (inGeoIndex != kNoGeometry) {\n      const size_t numVertices = scene.inGeo[inGeoIndex].size();\n      assert(numVertices == scene.outGeo[outGeoIndex].size());\n      for (size_t i = 0; i < numVertices; ++i) {\n        const Vec3 worldPos = multiply(scene.inGeo[inGeoIndex][i], transform.worldMatrix);\n        result = result && compare(scene.outGeo[outGeoIndex][i], worldPos);\n      }\n    }\n  }\n  return result;\n}\nvoid cleanScene(Scene& s) {\n  for (Geometry& g : s.inGeo) {\n    g.clear();\n  }\n  for (Geometry& g : s.outGeo) {\n    g.clear();\n  }\n  for (Transform& t : s.transforms) {\n    std::fill(t.worldMatrix.begin(), t.worldMatrix.end(), 0.f);\n  }\n}\n\n#endif\n} // anonymous namespace\n\nstatic void BM_scene_graph_parallel_for(benchmark::State& state) {\n  // transform inGeo\n  dispenso::ThreadPool& threadPool = dispenso::globalThreadPool();\n\n  dispenso::Graph g;\n  Scene scene;\n  prepareGraph(threadPool, scene, g);\n\n  dispenso::ParallelForExecutor parallelForExecutor;\n\n  dispenso::TaskSet taskSet(threadPool);\n\n  for (auto _ : state) {\n    state.PauseTiming();\n    setAllNodesIncomplete(g);\n    state.ResumeTiming();\n\n    parallelForExecutor(taskSet, g);\n\n#ifndef NDEBUG\n    state.PauseTiming();\n    assert(testScene(scene));\n    cleanScene(scene);\n    state.ResumeTiming();\n#endif\n  }\n}\n\nstatic void BM_scene_graph_concurrent_task_set(benchmark::State& state) {\n  // transform inGeo\n  dispenso::ThreadPool& threadPool = dispenso::globalThreadPool();\n\n  dispenso::Graph g;\n  Scene scene;\n  prepareGraph(threadPool, scene, g);\n\n  dispenso::ConcurrentTaskSet concurrentTaskSet(threadPool);\n  dispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\n\n  for (auto _ : state) {\n    state.PauseTiming();\n    setAllNodesIncomplete(g);\n    state.ResumeTiming();\n\n    concurrentTaskSetExecutor(concurrentTaskSet, g);\n    concurrentTaskSet.wait();\n\n#ifndef NDEBUG\n    state.PauseTiming();\n    assert(testScene(scene));\n    cleanScene(scene);\n    state.ResumeTiming();\n#endif\n  }\n}\n\nstatic void BM_scene_graph_partial_revaluation(benchmark::State& state) {\n  dispenso::ThreadPool& threadPool = dispenso::globalThreadPool();\n\n  std::mt19937 rng(123456);\n\n  dispenso::Graph g;\n  Scene scene;\n  Subgraphs subgraphs = prepareGraph(threadPool, scene, g);\n\n  const size_t numTransforms = scene.transforms.size();\n  std::uniform_real_distribution<float> transformIndexDistr(0, numTransforms - 1);\n\n  dispenso::ConcurrentTaskSet concurrentTaskSet(threadPool);\n  dispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\n  dispenso::ForwardPropagator forwardPropagator;\n\n  setAllNodesIncomplete(g);\n  concurrentTaskSetExecutor(concurrentTaskSet, g);\n  concurrentTaskSet.wait();\n\n  assert(testScene(scene));\n\n  for (auto _ : state) {\n    state.PauseTiming();\n    // change several transforms\n    rng.seed(123456);\n    for (size_t i = 0; i < 10; ++i) {\n      const size_t index = transformIndexDistr(rng);\n      Transform& t = scene.transforms[index];\n      t.matrix = getRandomTransformMatrix(rng);\n      subgraphs.transforms->node(index).setIncomplete();\n    }\n    state.ResumeTiming();\n    // The graph automatically recalculates all children of modified transforms. If these transforms\n    // have geometry this geometry will be recomputed as well.\n    forwardPropagator(g);\n    concurrentTaskSetExecutor(concurrentTaskSet, g);\n    concurrentTaskSet.wait();\n#ifndef NDEBUG\n    state.PauseTiming();\n    assert(testScene(scene));\n    state.ResumeTiming();\n#endif\n  }\n}\n// TODO(roman fedotov): Add partial evaluation variant for taskflow (possible implementation:\n// conditional tasks)\n\nstatic void BM_scene_graph_taskflow(benchmark::State& state) {\n  tf::Taskflow taskflow;\n\n  Scene scene;\n  prepareGraphTF(taskflow, scene);\n\n  tf::Executor executor;\n  for (auto _ : state) {\n    executor.run(taskflow).wait();\n\n#ifndef NDEBUG\n    state.PauseTiming();\n    assert(testScene(scene));\n    cleanScene(scene);\n    state.ResumeTiming();\n#endif\n  }\n}\n\nBENCHMARK(BM_scene_graph_parallel_for)->UseRealTime();\nBENCHMARK(BM_scene_graph_concurrent_task_set)->UseRealTime();\nBENCHMARK(BM_scene_graph_taskflow)->UseRealTime();\n\n#ifndef NDEBUG\nBENCHMARK(BM_scene_graph_partial_revaluation)->UseRealTime()->Iterations(50);\n#else\nBENCHMARK(BM_scene_graph_partial_revaluation)->UseRealTime();\n#endif\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/idle_pool_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Benchmarks for thread pool behavior under low/idle workloads.\n * Tests CPU usage and responsiveness when threads are mostly waiting.\n */\n\n#include <chrono>\n\n#include <dispenso/task_set.h>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include <tbb/task_group.h>\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nusing namespace std::chrono_literals;\n\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 10000;\nstatic constexpr int kLargeSize = 1000000;\n\nstruct alignas(64) Work {\n  size_t count = 0;\n\n  void operator+=(size_t o) {\n    count += o;\n  }\n};\n\nWork g_work[1025];\nstd::atomic<int> g_tCounter{0};\ninline int testTid() {\n  static DISPENSO_THREAD_LOCAL int t = -1;\n  if (t < 0) {\n    t = g_tCounter.fetch_add(1, std::memory_order_acq_rel);\n  }\n  return t;\n}\n\ninline Work& work() {\n  static DISPENSO_THREAD_LOCAL Work* w = nullptr;\n\n  if (!w) {\n    if (testTid() == 0) {\n      w = g_work + 1024;\n    } else {\n      w = g_work + (testTid() & 1023);\n    }\n  }\n  return *w;\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb_mostly_idle(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  struct Recurse {\n    void operator()() const {\n      work() += i;\n      if (i < num_elements) {\n        ++i;\n        g->run(*this);\n      }\n    }\n\n    mutable int i;\n    mutable tbb::task_group* g;\n    int num_elements;\n  };\n\n  tbb_compat::task_scheduler_init initsched(num_threads);\n\n  startRusage();\n\n  for (auto UNUSED_VAR : state) {\n    tbb::task_group g;\n    Recurse rec;\n    rec.i = 0;\n    rec.g = &g;\n    rec.num_elements = num_elements;\n    rec();\n    g.wait();\n  }\n  endRusage(state);\n}\n\nvoid BM_tbb_very_idle(benchmark::State& state) {\n  const int num_threads = state.range(0);\n\n  tbb_compat::task_scheduler_init initsched(num_threads);\n\n  startRusage();\n\n  for (auto UNUSED_VAR : state) {\n    tbb::task_group g;\n    g.run([]() {});\n    std::this_thread::sleep_for(100ms);\n    g.run([]() {});\n    g.wait();\n  }\n  endRusage(state);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_mostly_idle(benchmark::State& state) {\n  const int num_threads = std::max<int>(1, state.range(0) - 1);\n  const int num_elements = state.range(1);\n\n  struct Recurse {\n    void operator()() {\n      work() += i;\n      if (i < num_elements) {\n        ++i;\n        tasks->schedule(*this);\n      }\n    }\n\n    int i;\n    dispenso::ConcurrentTaskSet* tasks;\n    int num_elements;\n  };\n\n  dispenso::ThreadPool pool(num_threads);\n\n  startRusage();\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::ConcurrentTaskSet tasks(pool);\n    Recurse rec;\n    rec.i = 0;\n    rec.tasks = &tasks;\n    rec.num_elements = num_elements;\n    rec();\n    tasks.wait();\n  }\n\n  endRusage(state);\n}\n\nvoid BM_dispenso_very_idle(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  dispenso::ThreadPool pool(num_threads);\n  startRusage();\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    tasks.schedule([]() {});\n    std::this_thread::sleep_for(100ms);\n    tasks.schedule([]() {});\n    // TaskSet destructor waits for both tasks, mirroring TBB's g.wait()\n  }\n\n  endRusage(state);\n}\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int s : pow2HalfStepThreads()) {\n      b->Args({s, j});\n    }\n  }\n}\n\nstatic void CustomArgumentsVeryIdle(benchmark::internal::Benchmark* b) {\n  for (int s : pow2HalfStepThreads()) {\n    b->Args({s});\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_mostly_idle)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\nBENCHMARK(BM_tbb_very_idle)\n    ->Apply(CustomArgumentsVeryIdle)\n    ->Unit(benchmark::kMicrosecond)\n    ->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\nBENCHMARK(BM_dispenso_mostly_idle)\n    ->Apply(CustomArguments)\n    ->Unit(benchmark::kMicrosecond)\n    ->UseRealTime();\nBENCHMARK(BM_dispenso_very_idle)\n    ->Apply(CustomArgumentsVeryIdle)\n    ->Unit(benchmark::kMicrosecond)\n    ->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/locality_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Benchmark for cache/NUMA-sensitive workloads.\n *\n * Tests a repeated stencil pattern over large arrays (exceeding L3 cache)\n * where deterministic thread-to-memory mapping (kStatic) may outperform\n * dynamic chunking (kAuto) due to cache locality and NUMA effects.\n *\n * The work per element is intentionally trivial (memory-bound) so that\n * memory access patterns dominate performance, not compute.\n */\n\n// MSVC uses __restrict, GCC/Clang use __restrict__\n#ifdef _MSC_VER\n#define RESTRICT __restrict\n#else\n#define RESTRICT __restrict__\n#endif\n\n#include <cstring>\n#include <numeric>\n#include <vector>\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_for.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\n// ~32MB per array (4M doubles). Two arrays = 64MB, exceeds typical per-core L2\n// but may fit in shared L3 on some machines. Scale up if needed.\nstatic constexpr size_t kSmallSize = 100000; // ~800KB per array\nstatic constexpr size_t kMediumSize = 4000000; // ~32MB per array\nstatic constexpr size_t kLargeSize = 32000000; // ~256MB per array\n\nstatic constexpr int kPasses = 10;\n\n// Initialize arrays with deterministic data.\nstatic void initArrays(std::vector<double>& input, std::vector<double>& output, size_t n) {\n  input.resize(n);\n  output.resize(n);\n  for (size_t i = 0; i < n; ++i) {\n    input[i] = static_cast<double>(i % 1000) * 0.001;\n  }\n  std::memset(output.data(), 0, n * sizeof(double));\n}\n\n// Simple 3-point stencil: output[i] = 0.25 * (input[i-1] + 2*input[i] + input[i+1])\n// Cheap compute, memory-bound. Multiple passes amplify locality effects.\ninline void\nstencilPass(const double* RESTRICT src, double* RESTRICT dst, size_t begin, size_t end, size_t n) {\n  for (size_t i = begin; i < end; ++i) {\n    size_t im = (i > 0) ? i - 1 : 0;\n    size_t ip = (i < n - 1) ? i + 1 : n - 1;\n    dst[i] = 0.25 * (src[im] + 2.0 * src[i] + src[ip]);\n  }\n}\n\n// Verify output is non-garbage (spot-check a few values).\nstatic void checkOutput(const double* data, size_t n) {\n  if (n == 0)\n    return;\n  // After stencil passes, values should be finite and in a reasonable range.\n  for (size_t i = 0; i < n; i += n / 10 + 1) {\n    if (!std::isfinite(data[i])) {\n      std::cerr << \"FAIL: non-finite value at index \" << i << std::endl;\n      abort();\n    }\n  }\n}\n\ntemplate <size_t num_elements>\nvoid BM_serial(benchmark::State& state) {\n  std::vector<double> input, output;\n  initArrays(input, output, num_elements);\n\n  for (auto UNUSED_VAR : state) {\n    for (int pass = 0; pass < kPasses; ++pass) {\n      stencilPass(input.data(), output.data(), 0, num_elements, num_elements);\n      std::swap(input, output);\n    }\n  }\n  checkOutput(input.data(), num_elements);\n}\n\nvoid BM_dispenso_static(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const size_t num_elements = state.range(1);\n\n  std::vector<double> input, output;\n  initArrays(input, output, num_elements);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    for (int pass = 0; pass < kPasses; ++pass) {\n      dispenso::TaskSet tasks(pool);\n      const double* src = input.data();\n      double* dst = output.data();\n      auto range =\n          dispenso::makeChunkedRange(size_t{0}, num_elements, dispenso::ParForChunking::kStatic);\n      dispenso::parallel_for(tasks, range, [src, dst, num_elements](size_t begin, size_t end) {\n        stencilPass(src, dst, begin, end, num_elements);\n      });\n      std::swap(input, output);\n    }\n  }\n  checkOutput(input.data(), num_elements);\n}\n\nvoid BM_dispenso_auto(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const size_t num_elements = state.range(1);\n\n  std::vector<double> input, output;\n  initArrays(input, output, num_elements);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    for (int pass = 0; pass < kPasses; ++pass) {\n      dispenso::TaskSet tasks(pool);\n      const double* src = input.data();\n      double* dst = output.data();\n      auto range =\n          dispenso::makeChunkedRange(size_t{0}, num_elements, dispenso::ParForChunking::kAuto);\n      dispenso::parallel_for(tasks, range, [src, dst, num_elements](size_t begin, size_t end) {\n        stencilPass(src, dst, begin, end, num_elements);\n      });\n      std::swap(input, output);\n    }\n  }\n  checkOutput(input.data(), num_elements);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const size_t num_elements = state.range(1);\n\n  std::vector<double> input, output;\n  initArrays(input, output, num_elements);\n\n  omp_set_num_threads(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    for (int pass = 0; pass < kPasses; ++pass) {\n      const double* src = input.data();\n      double* dst = output.data();\n#pragma omp parallel for schedule(static)\n      for (int64_t i = 0; i < static_cast<int64_t>(num_elements); ++i) {\n        size_t im = (i > 0) ? i - 1 : 0;\n        size_t ip = (i < num_elements - 1) ? i + 1 : num_elements - 1;\n        dst[i] = 0.25 * (src[im] + 2.0 * src[i] + src[ip]);\n      }\n      std::swap(input, output);\n    }\n  }\n  checkOutput(input.data(), num_elements);\n}\n#endif /* defined(_OPENMP) */\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const size_t num_elements = state.range(1);\n\n  std::vector<double> input, output;\n  initArrays(input, output, num_elements);\n\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(num_threads);\n    for (int pass = 0; pass < kPasses; ++pass) {\n      const double* src = input.data();\n      double* dst = output.data();\n      tbb::parallel_for(\n          tbb::blocked_range<size_t>(0, num_elements),\n          [src, dst, num_elements](const tbb::blocked_range<size_t>& r) {\n            stencilPass(src, dst, r.begin(), r.end(), num_elements);\n          });\n      std::swap(input, output);\n    }\n  }\n  checkOutput(input.data(), num_elements);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (size_t j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : {1, 4, 16, 64, 128}) {\n      b->Args({i, static_cast<int64_t>(j)});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso_static)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_auto)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/nested_for_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <cmath>\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_reduce.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nnamespace {\nconstexpr int kWorkMultiplier = 4;\nconstexpr int kSmallSize = 10;\nconstexpr int kMediumSize = 500;\nconstexpr int kLargeSize = 2500;\n\nint g_numThreads = 0;\n} // namespace\n\nuint32_t getInputs(int numElements) {\n  srand(numElements);\n  return rand() & 127;\n}\n\ninline uint64_t calculate(uint64_t input, uint64_t index, size_t foo) {\n  return std::cos(\n      std::log(\n          std::sin(std::exp(std::sqrt(static_cast<double>((input ^ index) - 3 * foo * input))))));\n}\n\nuint64_t calculateInnerSerial(uint64_t input, size_t foo, int numElements) {\n  uint64_t sum = 0;\n  for (size_t i = 0; i < kWorkMultiplier * numElements; ++i) {\n    sum += calculate(input, i, foo);\n  }\n  return sum;\n}\n\nvoid checkResults(uint32_t input, uint64_t actual, int foo, size_t numElements) {\n  if (!foo)\n    return;\n  if (input != getInputs(numElements)) {\n    std::cerr << \"Failed to recover input!\" << std::endl;\n    abort();\n  }\n  uint64_t expected = 0;\n  for (size_t i = 0; i < numElements; ++i) {\n    expected += calculateInnerSerial(input, foo, numElements);\n  }\n  if (expected != actual) {\n    std::cerr << \"FAIL! \" << expected << \" vs \" << actual << std::endl;\n    abort();\n  }\n}\n\ntemplate <int numElements>\nvoid BM_serial(benchmark::State& state) {\n  auto input = getInputs(numElements);\n  uint64_t sum = 0;\n  int foo = 0;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n    for (size_t j = 0; j < numElements; ++j) {\n      sum += calculateInnerSerial(input, foo, numElements);\n    }\n  }\n  checkResults(input, sum, foo, numElements);\n}\n\nuint64_t calculateInnerDispenso(uint64_t input, size_t foo, int numElements) {\n  std::vector<uint64_t> sums;\n  sums.reserve(g_numThreads + 1);\n  dispenso::parallel_for(\n      sums,\n      []() { return uint64_t{0}; },\n      0,\n      kWorkMultiplier * numElements,\n      [input, foo](uint64_t& lsumStore, size_t i, size_t end) {\n        uint64_t lsum = 0;\n        for (; i != end; ++i) {\n          lsum += calculate(input, i, foo);\n        }\n        lsumStore += lsum;\n      });\n  uint64_t sum = 0;\n  for (auto s : sums) {\n    sum += s;\n  }\n  return sum;\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  g_numThreads = state.range(0) - 1;\n  const int numElements = state.range(1);\n\n  dispenso::resizeGlobalThreadPool(g_numThreads);\n\n  uint64_t sum = 0;\n  int foo = 0;\n\n  auto input = getInputs(numElements);\n  for (auto UNUSED_VAR : state) {\n    std::vector<uint64_t> sums;\n    sums.reserve(g_numThreads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        sums,\n        []() { return uint64_t{0}; },\n        0,\n        numElements,\n        [numElements, input, foo](uint64_t& lsumStore, size_t j, size_t end) {\n          uint64_t lsum = 0;\n          for (; j != end; ++j) {\n            lsum += calculateInnerDispenso(input, foo, numElements);\n          }\n          lsumStore += lsum;\n        });\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo, numElements);\n}\n\nuint64_t calculateInnerDispensoAuto(uint64_t input, size_t foo, int numElements) {\n  std::vector<uint64_t> sums;\n  sums.reserve(g_numThreads + 1);\n  dispenso::ParForOptions options;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n  dispenso::parallel_for(\n      sums,\n      []() { return uint64_t{0}; },\n      0,\n      kWorkMultiplier * numElements,\n      [input, foo](uint64_t& lsumStore, size_t i, size_t end) {\n        uint64_t lsum = 0;\n        for (; i != end; ++i) {\n          lsum += calculate(input, i, foo);\n        }\n        lsumStore += lsum;\n      },\n      options);\n  uint64_t sum = 0;\n  for (auto s : sums) {\n    sum += s;\n  }\n  return sum;\n}\n\nvoid BM_dispenso_auto(benchmark::State& state) {\n  g_numThreads = state.range(0) - 1;\n  const int numElements = state.range(1);\n\n  dispenso::resizeGlobalThreadPool(g_numThreads);\n\n  uint64_t sum = 0;\n  int foo = 0;\n\n  dispenso::ParForOptions options;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n\n  auto input = getInputs(numElements);\n  for (auto UNUSED_VAR : state) {\n    std::vector<uint64_t> sums;\n    sums.reserve(g_numThreads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        sums,\n        []() { return uint64_t{0}; },\n        0,\n        numElements,\n        [numElements, input, foo](uint64_t& lsumStore, size_t j, size_t end) {\n          uint64_t lsum = 0;\n          for (; j != end; ++j) {\n            lsum += calculateInnerDispensoAuto(input, foo, numElements);\n          }\n          lsumStore += lsum;\n        },\n        options);\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo, numElements);\n}\n\n#if defined(_OPENMP)\nuint64_t calculateInnerOmp(uint64_t input, size_t foo, int numElements) {\n  uint64_t sum = 0;\n#pragma omp parallel for reduction(+ : sum)\n  for (int i = 0; i < kWorkMultiplier * numElements; ++i) {\n    sum += calculate(input, i, foo);\n  }\n  return sum;\n}\n\nvoid BM_omp(benchmark::State& state) {\n  g_numThreads = state.range(0);\n  const int numElements = state.range(1);\n\n  omp_set_num_threads(g_numThreads);\n\n  uint64_t sum = 0;\n\n  int foo = 0;\n\n  auto input = getInputs(numElements);\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n#pragma omp parallel for reduction(+ : sum)\n    for (int i = 0; i < numElements; ++i) {\n      sum += calculateInnerOmp(input, foo, numElements);\n    }\n  }\n  checkResults(input, sum, foo, numElements);\n}\n#endif /*defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nuint64_t calculateInnerTbb(uint64_t input, size_t foo, int numElements) {\n  return tbb::parallel_reduce(\n      tbb::blocked_range<size_t>(0, kWorkMultiplier * numElements),\n      uint64_t{0},\n      [input, foo](const tbb::blocked_range<size_t>& r, uint64_t init) -> uint64_t {\n        for (size_t a = r.begin(); a != r.end(); ++a)\n          init += calculate(input, a, foo);\n        return init;\n      },\n      [](uint64_t x, uint64_t y) -> uint64_t { return x + y; });\n}\n\nvoid BM_tbb(benchmark::State& state) {\n  g_numThreads = state.range(0);\n  const int numElements = state.range(1);\n\n  uint64_t sum = 0;\n\n  int foo = 0;\n\n  auto input = getInputs(numElements);\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(g_numThreads);\n    ++foo;\n    sum = tbb::parallel_reduce(\n        tbb::blocked_range<size_t>(0, numElements),\n        uint64_t{0},\n        [numElements, input, foo](const tbb::blocked_range<size_t>& r, uint64_t init) -> uint64_t {\n          for (size_t a = r.begin(); a != r.end(); ++a)\n            init += calculateInnerTbb(input, foo, numElements);\n          return init;\n        },\n        [](uint64_t x, uint64_t y) -> uint64_t { return x + y; });\n  }\n  checkResults(input, sum, foo, numElements);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_auto)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/nested_pool_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Benchmarks for nested/hierarchical task scheduling patterns.\n * Tests scenarios where tasks spawn additional child tasks.\n */\n\n#include <cmath>\n\n#include <dispenso/task_set.h>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include <tbb/task_group.h>\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\n#include <folly/VirtualExecutor.h>\n#include <folly/coro/BlockingWait.h>\n#include <folly/coro/Collect.h>\n#include <folly/coro/Coroutine.h>\n#include <folly/coro/Task.h>\n#include <folly/executors/CPUThreadPoolExecutor.h>\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\n#include \"thread_benchmark_common.h\"\n\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 10000;\nstatic constexpr int kLargeSize = 300000;\n\nstruct alignas(64) Work {\n  size_t count = 0;\n\n  void operator+=(size_t o) {\n    count += o;\n  }\n};\n\nWork g_work[1025];\nstd::atomic<int> g_tCounter{0};\ninline int testTid() {\n  static DISPENSO_THREAD_LOCAL int t = -1;\n  if (t < 0) {\n    t = g_tCounter.fetch_add(1, std::memory_order_acq_rel);\n  }\n  return t;\n}\n\ninline Work& work() {\n  static DISPENSO_THREAD_LOCAL Work* w = nullptr;\n\n  if (!w) {\n    if (testTid() == 0) {\n      w = g_work + 1024;\n    } else {\n      w = g_work + (testTid() & 1023);\n    }\n  }\n  return *w;\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet outerTasks(pool);\n    for (int i = 0; i < num_elements; ++i) {\n      outerTasks.schedule([&pool, num_elements]() {\n        int num = std::sqrt(num_elements);\n        dispenso::TaskSet tasks(pool);\n        for (int j = 0; j < num; ++j) {\n          tasks.schedule([j]() { work() += j; });\n        }\n      });\n    }\n  }\n}\n\nvoid BM_dispenso_bulk(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet outerTasks(pool);\n    outerTasks.scheduleBulk(static_cast<size_t>(num_elements), [&pool, num_elements](size_t) {\n      return [&pool, num_elements]() {\n        int num = std::sqrt(num_elements);\n        dispenso::TaskSet tasks(pool);\n        tasks.scheduleBulk(\n            static_cast<size_t>(num), [](size_t j) { return [j]() { work() += j; }; });\n      };\n    });\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  tbb_compat::task_scheduler_init initsched(num_threads);\n  for (auto UNUSED_VAR : state) {\n    tbb::task_group g;\n    for (int i = 0; i < num_elements; ++i) {\n      g.run([num_elements]() {\n        int num = std::sqrt(num_elements);\n        tbb::task_group g2;\n        for (int j = 0; j < num; ++j) {\n          g2.run([j]() { work() += j; });\n        }\n        g2.wait();\n      });\n    }\n    g.wait();\n  }\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nvoid BM_folly(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  if (num_elements > 10000) {\n    state.SkipWithError(\"We run out of memory here with too many elements\");\n  }\n\n  folly::CPUThreadPoolExecutor follyExec(num_threads);\n  for (auto UNUSED_VAR : state) {\n    folly::coro::blockingWait([&]() -> folly::coro::Task<void> {\n      std::vector<folly::coro::Task<void>> tasks;\n      for (int i = 0; i < num_elements; ++i) {\n        tasks.push_back(folly::coro::co_invoke([num_elements]() -> folly::coro::Task<void> {\n          co_await folly::coro::co_reschedule_on_current_executor;\n          std::vector<folly::coro::Task<void>> tasks2;\n          int num = std::sqrt(num_elements);\n          for (int j = 0; j < num; ++j) {\n            tasks2.push_back(folly::coro::co_invoke([j]() -> folly::coro::Task<void> {\n              co_await folly::coro::co_reschedule_on_current_executor;\n              work() += j;\n            }));\n          }\n          co_await folly::coro::collectAllRange(std::move(tasks2));\n        }));\n      }\n      co_await folly::coro::collectAllRange(std::move(tasks)).scheduleOn(&follyExec);\n    }());\n  }\n}\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int s : pow2HalfStepThreads()) {\n      b->Args({s, j});\n    }\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nBENCHMARK(BM_folly)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_FOLLY\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\nBENCHMARK(BM_dispenso_bulk)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/once_function_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <cstring>\n#include <deque>\n#include <functional>\n\n#include <dispenso/once_function.h>\n\n#include \"benchmark_common.h\"\n\nconstexpr size_t kSmallSize = 24;\nconstexpr size_t kMediumSize = 120;\nconstexpr size_t kLargeSize = 248;\n// 1000 is larger than our largest optimized chunk size, so we may expect to see performance falloff\n// here.\nconstexpr size_t kExtraLargeSize = 1000;\n\ntemplate <typename ExeType, typename Func>\nvoid runMoveLoop(benchmark::State& state, Func f) {\n  for (auto UNUSED_VAR : state) {\n    ExeType t(f);\n    ExeType o;\n    for (int i = 0; i < 10; ++i) {\n      o = std::move(t);\n      t = std::move(o);\n    }\n    t();\n  }\n}\n\ntemplate <typename Func>\nclass FuncConsumer {\n public:\n  void add(Func&& f) {\n    funcs_.emplace_back(std::move(f));\n  }\n\n  void consumeAll() {\n    while (!funcs_.empty()) {\n      Func f = std::move(funcs_.front());\n      funcs_.pop_front();\n      f();\n    }\n  }\n\n private:\n  std::deque<Func> funcs_;\n};\n\ntemplate <size_t kSize>\nstruct Foo {\n  Foo() {\n    buf[0] = 0;\n    benchmark::ClobberMemory();\n  }\n\n  Foo(Foo<kSize>&& f) {\n    std::memcpy(buf, f.buf, kSize);\n  }\n\n  Foo(const Foo<kSize>& f) {\n    std::memcpy(buf, f.buf, kSize);\n  }\n\n  void operator()() {\n    benchmark::DoNotOptimize(++buf[0]);\n  }\n\n  uint32_t buf[kSize / 4];\n};\n\ntemplate <typename F>\nvoid onceCall(F&& f) {\n  F lf = std::move(f);\n  lf();\n}\n\ntemplate <size_t kSize>\nvoid BM_move_std_function(benchmark::State& state) {\n  runMoveLoop<std::function<void()>>(state, Foo<kSize>());\n}\n\ntemplate <size_t kSize>\nvoid BM_move_once_function(benchmark::State& state) {\n  runMoveLoop<dispenso::OnceFunction>(state, Foo<kSize>());\n}\n\nconstexpr int kMediumLoopLen = 200;\n\ntemplate <size_t kSize>\nvoid BM_queue_inline_function(benchmark::State& state) {\n  FuncConsumer<Foo<kSize>> consumer;\n  for (auto UNUSED_VAR : state) {\n    for (int i = 0; i < kMediumLoopLen; ++i) {\n      consumer.add(Foo<kSize>());\n    }\n    consumer.consumeAll();\n  }\n}\n\ntemplate <size_t kSize>\nvoid BM_queue_std_function(benchmark::State& state) {\n  FuncConsumer<std::function<void()>> consumer;\n  for (auto UNUSED_VAR : state) {\n    for (int i = 0; i < kMediumLoopLen; ++i) {\n      consumer.add(Foo<kSize>());\n    }\n    consumer.consumeAll();\n  }\n}\n\ntemplate <size_t kSize>\nvoid BM_queue_once_function(benchmark::State& state) {\n  FuncConsumer<dispenso::OnceFunction> consumer;\n  for (auto UNUSED_VAR : state) {\n    for (int i = 0; i < kMediumLoopLen; ++i) {\n      consumer.add(Foo<kSize>());\n    }\n    consumer.consumeAll();\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_move_std_function, kSmallSize);\nBENCHMARK_TEMPLATE(BM_move_once_function, kSmallSize);\n\nBENCHMARK_TEMPLATE(BM_move_std_function, kMediumSize);\nBENCHMARK_TEMPLATE(BM_move_once_function, kMediumSize);\n\nBENCHMARK_TEMPLATE(BM_move_std_function, kLargeSize);\nBENCHMARK_TEMPLATE(BM_move_once_function, kLargeSize);\n\nBENCHMARK_TEMPLATE(BM_move_std_function, kExtraLargeSize);\nBENCHMARK_TEMPLATE(BM_move_once_function, kExtraLargeSize);\n\nBENCHMARK_TEMPLATE(BM_queue_inline_function, kSmallSize);\nBENCHMARK_TEMPLATE(BM_queue_std_function, kSmallSize);\nBENCHMARK_TEMPLATE(BM_queue_once_function, kSmallSize);\n\nBENCHMARK_TEMPLATE(BM_queue_inline_function, kMediumSize);\nBENCHMARK_TEMPLATE(BM_queue_std_function, kMediumSize);\nBENCHMARK_TEMPLATE(BM_queue_once_function, kMediumSize);\n\nBENCHMARK_TEMPLATE(BM_queue_inline_function, kLargeSize);\nBENCHMARK_TEMPLATE(BM_queue_std_function, kLargeSize);\nBENCHMARK_TEMPLATE(BM_queue_once_function, kLargeSize);\n\nBENCHMARK_TEMPLATE(BM_queue_inline_function, kExtraLargeSize);\nBENCHMARK_TEMPLATE(BM_queue_std_function, kExtraLargeSize);\nBENCHMARK_TEMPLATE(BM_queue_once_function, kExtraLargeSize);\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/pipeline_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <cmath>\n#include <cstdlib>\n#include <cstring>\n#include <iostream>\n#include <random>\n\n#include <dispenso/pipeline.h>\n\n#include \"benchmark_common.h\"\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include <taskflow/taskflow.hpp>\n#if TF_VERSION > 300000\n#include <taskflow/algorithm/pipeline.hpp>\n#endif // TF_VERSION\n\n// (1) Generate images\n// (2) Calculate geometric mean\n// (3) Tonemap based on geometric mean\n\nconstexpr size_t kWidth = 256;\nconstexpr size_t kHeight = 256;\nconstexpr size_t kNumImages = 500;\nconstexpr size_t kSeed = 55;\n\nstruct Work {\n  Work(size_t idx) : index(idx) {}\n\n  Work(Work&& w)\n      : index(w.index), geometricMean(w.geometricMean), inputImage(std::move(w.inputImage)) {}\n\n  Work& operator=(Work&& w) {\n    index = w.index;\n    geometricMean = w.geometricMean;\n    inputImage = std::move(w.inputImage);\n    return *this;\n  }\n\n  size_t index;\n  double geometricMean = 0;\n  std::unique_ptr<uint16_t[]> inputImage;\n};\n\nstd::vector<std::unique_ptr<uint8_t[]>> g_serialResults;\n\nWork fillImage(Work work) {\n  std::mt19937 rng(kSeed + work.index);\n\n  work.inputImage = std::make_unique<uint16_t[]>(kWidth * kHeight);\n  std::uniform_int_distribution<uint16_t> dist;\n\n  for (size_t i = 0; i < kWidth * kHeight; ++i) {\n    work.inputImage[i] = dist(rng);\n  }\n\n  return work;\n}\n\nWork computeGeometricMean(Work work) {\n  double sum = 0;\n  for (size_t i = 0; i < kWidth * kHeight; ++i) {\n    sum += std::log(1.0e-10 + work.inputImage[i]);\n  }\n  work.geometricMean = std::exp(sum / (kWidth * kHeight));\n  return work;\n}\n\nstd::unique_ptr<uint8_t[]> tonemap(Work work) {\n  auto out = std::make_unique<uint8_t[]>(kWidth * kHeight);\n  for (size_t i = 0; i < kWidth * kHeight; ++i) {\n    double adjLum = work.inputImage[i] / work.geometricMean;\n    out[i] = 255 * adjLum / (1.0 + adjLum);\n  }\n  return out;\n}\n\nvoid runSerial() {\n  g_serialResults.resize(kNumImages);\n\n  size_t index = 0;\n  for (auto& out : g_serialResults) {\n    out = tonemap(computeGeometricMean(fillImage(Work(index++))));\n  }\n}\n\nvoid checkResults(const std::vector<std::unique_ptr<uint8_t[]>>& results) {\n  if (g_serialResults.empty()) {\n    runSerial();\n  }\n\n  if (g_serialResults.size() != results.size()) {\n    std::cerr << \"Number of results don't match\" << std::endl;\n    std::abort();\n  }\n\n  for (size_t i = 0; i < results.size(); ++i) {\n    if (std::memcmp(\n            g_serialResults[i].get(), results[i].get(), kWidth * kHeight * sizeof(uint8_t))) {\n      std::cerr << \"Mismatch in results\" << std::endl;\n\n      for (size_t j = 0; j < 10; ++j) {\n        std::cerr << (int)g_serialResults[i][j] << \" vs \" << (int)results[i][j] << std::endl;\n      }\n      std::abort();\n    }\n  }\n}\n\nvoid BM_serial(benchmark::State& state) {\n  for (auto UNUSED_VAR : state) {\n    runSerial();\n  }\n}\n\nvoid runDispenso(std::vector<std::unique_ptr<uint8_t[]>>& results) {\n  results.resize(kNumImages);\n\n  size_t counter = 0;\n\n  dispenso::pipeline(\n      [&counter]() -> dispenso::OpResult<Work> {\n        if (counter < kNumImages) {\n          return fillImage(Work(counter++));\n        }\n        return {};\n      },\n      computeGeometricMean,\n      [&results](Work work) {\n        size_t index = work.index;\n        results[index] = tonemap(std::move(work));\n      });\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n\n  (void)dispenso::globalThreadPool();\n\n  for (auto UNUSED_VAR : state) {\n    runDispenso(results);\n  }\n\n  checkResults(results);\n}\n\nvoid runDispensoPar(std::vector<std::unique_ptr<uint8_t[]>>& results) {\n  results.resize(kNumImages);\n  std::atomic<size_t> counter(0);\n\n  dispenso::pipeline(\n      dispenso::stage(\n          [&counter]() -> dispenso::OpResult<Work> {\n            size_t curIndex = counter.fetch_add(1, std::memory_order_acquire);\n            if (curIndex < kNumImages) {\n              return fillImage(Work(curIndex));\n            }\n            return {};\n          },\n          dispenso::kStageNoLimit),\n      dispenso::stage(computeGeometricMean, dispenso::kStageNoLimit),\n      dispenso::stage(\n          [&results](Work work) {\n            size_t index = work.index;\n            results[index] = tonemap(std::move(work));\n          },\n          dispenso::kStageNoLimit));\n}\n\nvoid BM_dispenso_par(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n\n  (void)dispenso::globalThreadPool();\n\n  for (auto UNUSED_VAR : state) {\n    runDispensoPar(results);\n  }\n\n  checkResults(results);\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid runTBB(std::vector<std::unique_ptr<uint8_t[]>>& results) {\n  results.resize(kNumImages);\n\n  size_t counter = 0;\n  tbb::parallel_pipeline(\n      /*max_number_of_live_token=*/std::thread::hardware_concurrency(),\n      tbb::make_filter<void, Work*>(\n          tbb_compat::filter::serial,\n          [&counter](tbb::flow_control& fc) -> Work* {\n            if (counter < kNumImages) {\n              return new Work(fillImage(Work(counter++)));\n            }\n            fc.stop();\n            return nullptr;\n          }) &\n          tbb::make_filter<Work*, Work*>(\n              tbb_compat::filter::serial,\n              [](Work* workIn) {\n                Work& work = *workIn;\n                work = computeGeometricMean(std::move(work));\n                return workIn;\n              }) &\n          tbb::make_filter<Work*, void>(tbb_compat::filter::serial, [&results](Work* workIn) {\n            size_t index = workIn->index;\n            results[index] = tonemap(std::move(*workIn));\n            delete workIn;\n          }));\n}\n\nvoid BM_tbb(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n\n  for (auto UNUSED_VAR : state) {\n    runTBB(results);\n  }\n\n  checkResults(results);\n}\n\nvoid runTBBPar(std::vector<std::unique_ptr<uint8_t[]>>& results) {\n  results.resize(kNumImages);\n\n  std::atomic<size_t> counter(0);\n  tbb::parallel_pipeline(\n      /*max_number_of_live_token=*/std::thread::hardware_concurrency(),\n      tbb::make_filter<void, Work*>(\n          tbb_compat::filter::parallel,\n          [&counter](tbb::flow_control& fc) -> Work* {\n            size_t curIndex = counter.fetch_add(1, std::memory_order_acquire);\n            if (curIndex < kNumImages) {\n              return new Work(fillImage(Work(curIndex)));\n            }\n            fc.stop();\n            return nullptr;\n          }) &\n          tbb::make_filter<Work*, Work*>(\n              tbb_compat::filter::parallel,\n              [](Work* work) {\n                *work = computeGeometricMean(std::move(*work));\n                return work;\n              }) &\n          tbb::make_filter<Work*, void>(tbb_compat::filter::parallel, [&results](Work* work) {\n            size_t index = work->index;\n            results[index] = tonemap(std::move(*work));\n            delete work;\n          }));\n}\n\nvoid BM_tbb_par(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n\n  for (auto UNUSED_VAR : state) {\n    runTBBPar(results);\n  }\n\n  checkResults(results);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if TF_VERSION > 300000\nvoid runTaskflow(std::vector<std::unique_ptr<uint8_t[]>>& results, tf::Executor& exec) {\n  results.resize(kNumImages);\n  std::vector<std::unique_ptr<Work>> work;\n  // Ensure we don't resize underlying buffer causing data races\n  work.reserve(kNumImages);\n\n  tf::Taskflow taskflow;\n\n  size_t counter2 = 0;\n  size_t counter3 = 0;\n  tf::Pipeline pl(\n      std::thread::hardware_concurrency(),\n      tf::Pipe{\n          tf::PipeType::SERIAL,\n          [&work](auto& pf) mutable {\n            if (work.size() < kNumImages) {\n              work.push_back(std::make_unique<Work>(fillImage(Work(work.size()))));\n            } else {\n              pf.stop();\n            }\n          }},\n      tf::Pipe{\n          tf::PipeType::SERIAL,\n          [&counter2, &work](auto& pf) mutable {\n            Work& w = *work[counter2++];\n            w = computeGeometricMean(std::move(w));\n          }},\n      tf::Pipe{tf::PipeType::SERIAL, [&counter3, &work, &results](auto& pf) mutable {\n                 Work& w = *work[counter3];\n                 results[counter3++] = tonemap(std::move(w));\n               }});\n  taskflow.composed_of(pl);\n  exec.run(taskflow).wait();\n}\n\nvoid BM_taskflow(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n  tf::Executor executor(std::thread::hardware_concurrency());\n\n  for (auto UNUSED_VAR : state) {\n    runTaskflow(results, executor);\n  }\n\n  checkResults(results);\n}\n\nvoid runTaskflowPar(std::vector<std::unique_ptr<uint8_t[]>>& results, tf::Executor& exec) {\n  results.resize(kNumImages);\n  std::vector<std::unique_ptr<Work>> work(kNumImages);\n\n  tf::Taskflow taskflow;\n\n  tf::Pipeline pl(\n      std::thread::hardware_concurrency(),\n      tf::Pipe{\n          tf::PipeType::SERIAL, // First pipe must be serial in taskflow\n          [&work](tf::Pipeflow& pf) {\n            if (pf.token() >= kNumImages) {\n              pf.stop();\n              return;\n            }\n            work[pf.token()] = std::make_unique<Work>(fillImage(Work(pf.token())));\n          }},\n      tf::Pipe{\n          tf::PipeType::PARALLEL,\n          [&work](tf::Pipeflow& pf) {\n            Work& w = *work[pf.token()];\n            w = computeGeometricMean(std::move(w));\n          }},\n      tf::Pipe{tf::PipeType::PARALLEL, [&work, &results](tf::Pipeflow& pf) {\n                 size_t token = pf.token();\n                 results[token] = tonemap(std::move(*work[token]));\n               }});\n\n  taskflow.composed_of(pl);\n  exec.run(taskflow).wait();\n}\n\nvoid BM_taskflow_par(benchmark::State& state) {\n  std::vector<std::unique_ptr<uint8_t[]>> results;\n  tf::Executor executor(std::thread::hardware_concurrency());\n\n  for (auto UNUSED_VAR : state) {\n    runTaskflowPar(results, executor);\n  }\n\n  checkResults(results);\n}\n#endif // TF_VERSION > 300000\n\nBENCHMARK(BM_serial)->UseRealTime();\nBENCHMARK(BM_dispenso)->UseRealTime();\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n#if TF_VERSION > 300000\nBENCHMARK(BM_taskflow)->UseRealTime();\n#endif // TF_VERSION > 300000\n\nBENCHMARK(BM_dispenso_par)->UseRealTime();\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb_par)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if TF_VERSION > 300000\nBENCHMARK(BM_taskflow_par)->UseRealTime();\n#endif // TF_VERSION > 300000\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/pool_allocator_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/pool_allocator.h>\n\n#include <deque>\n\n#include <dispenso/task_set.h>\n\n#include \"benchmark_common.h\"\n\nconstexpr size_t kSmallSize = 1024;\nconstexpr size_t kMediumSize = 8192;\nconstexpr size_t kLargeSize = 65536;\n\ntemplate <typename Alloc, typename Free>\nvoid run(benchmark::State& state, Alloc alloc, Free dealloc) {\n  std::vector<char*> ptrs(state.range(0));\n  for (auto UNUSED_VAR : state) {\n    for (char*& p : ptrs) {\n      p = alloc();\n    }\n    for (char* p : ptrs) {\n      dealloc(p);\n    }\n  }\n}\n\ntemplate <typename PoolAlloc>\nvoid runArena(benchmark::State& state, PoolAlloc& allocator) {\n  std::vector<char*> ptrs(state.range(0));\n  for (auto UNUSED_VAR : state) {\n    for (char*& p : ptrs) {\n      p = allocator.alloc();\n    }\n    allocator.clear();\n  }\n}\n\ntemplate <size_t kSize>\nvoid BM_mallocfree(benchmark::State& state) {\n  run(\n      state,\n      []() { return reinterpret_cast<char*>(::malloc(kSize)); },\n      [](char* buf) { ::free(buf); });\n}\n\ntemplate <size_t kSize>\nvoid BM_pool_allocator(benchmark::State& state) {\n  dispenso::PoolAllocator allocator(kSize, kSize * 32, ::malloc, ::free);\n  run(\n      state,\n      [&allocator]() { return allocator.alloc(); },\n      [&allocator](char* buf) { allocator.dealloc(buf); });\n}\n\ntemplate <size_t kSize>\nvoid BM_nl_pool_allocator(benchmark::State& state) {\n  dispenso::NoLockPoolAllocator allocator(kSize, kSize * 32, ::malloc, ::free);\n  run(\n      state,\n      [&allocator]() { return allocator.alloc(); },\n      [&allocator](char* buf) { allocator.dealloc(buf); });\n}\n\ntemplate <size_t kSize>\nvoid BM_pool_allocator_arena(benchmark::State& state) {\n  dispenso::PoolAllocator allocator(kSize, kSize * 32, ::malloc, ::free);\n  runArena(state, allocator);\n}\n\ntemplate <size_t kSize>\nvoid BM_nl_pool_allocator_arena(benchmark::State& state) {\n  dispenso::NoLockPoolAllocator allocator(kSize, kSize * 32, ::malloc, ::free);\n  runArena(state, allocator);\n}\n\ntemplate <size_t kThreads, typename Alloc, typename Free>\nvoid runThreaded(benchmark::State& state, Alloc alloc, Free dealloc) {\n  dispenso::resizeGlobalThreadPool(kThreads);\n  std::vector<char*> ptrsArray[kThreads];\n  for (auto& ptrs : ptrsArray) {\n    ptrs.resize(state.range(0));\n  }\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(dispenso::globalThreadPool());\n    for (size_t i = 0; i < kThreads; ++i) {\n      tasks.schedule([alloc, dealloc, &ptrs = ptrsArray[i]]() {\n        for (char*& p : ptrs) {\n          p = alloc();\n        }\n        for (char* p : ptrs) {\n          dealloc(p);\n        }\n      });\n    }\n  }\n}\n\ntemplate <size_t kSize, size_t kThreads>\nvoid BM_mallocfree_threaded(benchmark::State& state) {\n  runThreaded<kThreads>(\n      state,\n      []() { return reinterpret_cast<char*>(::malloc(kSize)); },\n      [](char* buf) { ::free(buf); });\n}\n\ntemplate <size_t kSize, size_t kThreads>\nvoid BM_pool_allocator_threaded(benchmark::State& state) {\n  dispenso::PoolAllocator allocator(kSize, (1 << 20), ::malloc, ::free);\n  runThreaded<kThreads>(\n      state,\n      [&allocator]() { return allocator.alloc(); },\n      [&allocator](char* buf) { allocator.dealloc(buf); });\n}\n\nBENCHMARK_TEMPLATE(BM_mallocfree, kSmallSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_pool_allocator, kSmallSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator, kSmallSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_mallocfree, kMediumSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_pool_allocator, kMediumSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator, kMediumSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_mallocfree, kLargeSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_pool_allocator, kLargeSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator, kLargeSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_pool_allocator_arena, kSmallSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator_arena, kSmallSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_pool_allocator_arena, kMediumSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator_arena, kMediumSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_pool_allocator_arena, kLargeSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_nl_pool_allocator_arena, kLargeSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kSmallSize, 2)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kSmallSize, 2)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kMediumSize, 2)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kMediumSize, 2)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kLargeSize, 2)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kLargeSize, 2)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kSmallSize, 8)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kSmallSize, 8)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kMediumSize, 8)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kMediumSize, 8)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kLargeSize, 8)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kLargeSize, 8)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kSmallSize, 16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kSmallSize, 16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kMediumSize, 16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kMediumSize, 16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE2(BM_mallocfree_threaded, kLargeSize, 16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE2(BM_pool_allocator_threaded, kLargeSize, 16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/run_benchmarks.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"\nBenchmark runner and chart generator for dispenso.\n\nThis script runs the dispenso benchmarks, collects results, and generates\ncomparison charts. Results include machine information for reproducibility.\n\nUsage:\n    python run_benchmarks.py [--output-dir OUTPUT] [--benchmarks PATTERN]\n\nRequirements:\n    pip install matplotlib pandas\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport platform\nimport re\nimport subprocess\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any, Dict, List, Optional\n\ntry:\n    import matplotlib.pyplot as plt\n    import pandas as pd\n\n    HAS_PLOTTING = True\nexcept ImportError:\n    HAS_PLOTTING = False\n\n\ndef get_machine_info() -> Dict[str, Any]:\n    \"\"\"Gather machine information for benchmark context.\"\"\"\n    info = {\n        \"timestamp\": datetime.now().isoformat(),\n        \"platform\": platform.system(),\n        \"platform_release\": platform.release(),\n        \"platform_version\": platform.version(),\n        \"architecture\": platform.machine(),\n        \"processor\": platform.processor(),\n        \"python_version\": platform.python_version(),\n    }\n\n    # Try to get more detailed CPU info\n    if platform.system() == \"Linux\":\n        try:\n            with open(\"/proc/cpuinfo\", \"r\") as f:\n                cpuinfo = f.read()\n            # Extract model name\n            match = re.search(r\"model name\\s*:\\s*(.+)\", cpuinfo)\n            if match:\n                info[\"cpu_model\"] = match.group(1).strip()\n            # Count cores\n            info[\"cpu_cores\"] = cpuinfo.count(\"processor\\t:\")\n            # Get cache info\n            match = re.search(r\"cache size\\s*:\\s*(.+)\", cpuinfo)\n            if match:\n                info[\"cache_size\"] = match.group(1).strip()\n        except Exception as e:\n            info[\"cpu_info_error\"] = str(e)\n\n        # Memory info\n        try:\n            with open(\"/proc/meminfo\", \"r\") as f:\n                meminfo = f.read()\n            match = re.search(r\"MemTotal:\\s*(\\d+)\", meminfo)\n            if match:\n                info[\"memory_kb\"] = int(match.group(1))\n                info[\"memory_gb\"] = round(int(match.group(1)) / 1024 / 1024, 1)\n        except Exception:\n            pass\n\n    elif platform.system() == \"Darwin\":  # macOS\n        try:\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"machdep.cpu.brand_string\"],\n                capture_output=True,\n                text=True,\n            )\n            if result.returncode == 0:\n                info[\"cpu_model\"] = result.stdout.strip()\n\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"hw.ncpu\"], capture_output=True, text=True\n            )\n            if result.returncode == 0:\n                info[\"cpu_cores\"] = int(result.stdout.strip())\n\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"hw.memsize\"], capture_output=True, text=True\n            )\n            if result.returncode == 0:\n                mem_bytes = int(result.stdout.strip())\n                info[\"memory_gb\"] = round(mem_bytes / 1024 / 1024 / 1024, 1)\n        except Exception as e:\n            info[\"cpu_info_error\"] = str(e)\n\n    elif platform.system() == \"Windows\":\n        try:\n            import winreg\n\n            key = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\",\n            )\n            info[\"cpu_model\"] = winreg.QueryValueEx(key, \"ProcessorNameString\")[0]\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n\n        try:\n            result = subprocess.run(\n                [\"wmic\", \"computersystem\", \"get\", \"totalphysicalmemory\"],\n                capture_output=True,\n                text=True,\n            )\n            lines = result.stdout.strip().split(\"\\n\")\n            if len(lines) > 1:\n                mem_bytes = int(lines[1].strip())\n                info[\"memory_gb\"] = round(mem_bytes / 1024 / 1024 / 1024, 1)\n        except Exception:\n            pass\n\n        info[\"cpu_cores\"] = os.cpu_count()\n\n    return info\n\n\ndef find_benchmarks(build_dir: Path, pattern: Optional[str] = None) -> List[Path]:\n    \"\"\"Find benchmark executables in the build directory.\"\"\"\n    benchmarks = []\n\n    # Common locations\n    search_paths = [\n        build_dir / \"bin\",\n        build_dir / \"benchmarks\",\n        build_dir,\n    ]\n\n    for search_path in search_paths:\n        if not search_path.exists():\n            continue\n\n        for f in search_path.iterdir():\n            if not f.is_file():\n                continue\n            name = f.name\n            if \"benchmark\" in name.lower():\n                if pattern is None or re.search(pattern, name):\n                    benchmarks.append(f)\n\n    return sorted(benchmarks)\n\n\ndef run_benchmark(benchmark_path: Path, extra_args: List[str] = None) -> Dict[str, Any]:\n    \"\"\"Run a single benchmark and return results.\"\"\"\n    args = [str(benchmark_path), \"--benchmark_format=json\"]\n    if extra_args:\n        args.extend(extra_args)\n\n    print(f\"Running: {benchmark_path.name}...\")\n\n    try:\n        result = subprocess.run(\n            args,\n            capture_output=True,\n            text=True,\n            timeout=600,  # 10 minute timeout per benchmark\n        )\n\n        if result.returncode != 0:\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": False,\n                \"error\": result.stderr,\n            }\n\n        # Parse JSON output\n        # google benchmark outputs JSON to stdout\n        try:\n            data = json.loads(result.stdout)\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": True,\n                \"data\": data,\n            }\n        except json.JSONDecodeError:\n            # Maybe it's not a google benchmark, try to parse stdout\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": True,\n                \"raw_output\": result.stdout,\n            }\n\n    except subprocess.TimeoutExpired:\n        return {\n            \"name\": benchmark_path.name,\n            \"success\": False,\n            \"error\": \"Timeout after 600 seconds\",\n        }\n    except Exception as e:\n        return {\n            \"name\": benchmark_path.name,\n            \"success\": False,\n            \"error\": str(e),\n        }\n\n\ndef extract_benchmark_data(results: List[Dict]) -> pd.DataFrame:\n    \"\"\"Extract benchmark data into a DataFrame for plotting.\"\"\"\n    rows = []\n\n    for result in results:\n        if not result.get(\"success\") or \"data\" not in result:\n            continue\n\n        data = result[\"data\"]\n        benchmarks = data.get(\"benchmarks\", [])\n\n        for bm in benchmarks:\n            row = {\n                \"suite\": result[\"name\"].replace(\"_benchmark\", \"\"),\n                \"name\": bm.get(\"name\", \"unknown\"),\n                \"real_time\": bm.get(\"real_time\", 0),\n                \"cpu_time\": bm.get(\"cpu_time\", 0),\n                \"time_unit\": bm.get(\"time_unit\", \"ns\"),\n                \"iterations\": bm.get(\"iterations\", 0),\n            }\n\n            # Extract any custom counters\n            for key, value in bm.items():\n                if key not in row and isinstance(value, (int, float)):\n                    row[key] = value\n\n            rows.append(row)\n\n    return pd.DataFrame(rows)\n\n\ndef generate_charts(df: pd.DataFrame, output_dir: Path):\n    \"\"\"Generate comparison charts from benchmark data.\"\"\"\n    if df.empty:\n        print(\"No data to plot\")\n        return\n\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    # Group by suite\n    for suite, suite_df in df.groupby(\"suite\"):\n        fig, ax = plt.subplots(figsize=(12, 6))\n\n        # Bar chart of real_time\n        suite_df_sorted = suite_df.sort_values(\"real_time\")\n        bars = ax.barh(suite_df_sorted[\"name\"], suite_df_sorted[\"real_time\"])\n\n        ax.set_xlabel(f\"Time ({suite_df_sorted['time_unit'].iloc[0]})\")\n        ax.set_title(f\"{suite} Benchmark Results\")\n        ax.grid(axis=\"x\", alpha=0.3)\n\n        # Add value labels\n        for bar, val in zip(bars, suite_df_sorted[\"real_time\"]):\n            ax.text(\n                val,\n                bar.get_y() + bar.get_height() / 2,\n                f\" {val:.2f}\",\n                va=\"center\",\n                fontsize=8,\n            )\n\n        plt.tight_layout()\n        chart_path = output_dir / f\"{suite}_chart.png\"\n        plt.savefig(chart_path, dpi=150)\n        plt.close()\n        print(f\"Generated: {chart_path}\")\n\n    # Generate summary chart if multiple suites\n    if df[\"suite\"].nunique() > 1:\n        # This would need custom logic based on what comparisons make sense\n        pass\n\n\ndef generate_markdown_report(\n    machine_info: Dict[str, Any],\n    results: List[Dict],\n    df: pd.DataFrame,\n    output_dir: Path,\n):\n    \"\"\"Generate a markdown report of benchmark results.\"\"\"\n    report_path = output_dir / \"benchmark_report.md\"\n\n    with open(report_path, \"w\") as f:\n        f.write(\"# Dispenso Benchmark Results\\n\\n\")\n\n        # Machine info\n        f.write(\"## Machine Information\\n\\n\")\n        f.write(f\"- **Date**: {machine_info.get('timestamp', 'unknown')}\\n\")\n        f.write(\n            f\"- **Platform**: {machine_info.get('platform', 'unknown')} \"\n            f\"{machine_info.get('platform_release', '')}\\n\"\n        )\n        f.write(f\"- **CPU**: {machine_info.get('cpu_model', 'unknown')}\\n\")\n        f.write(f\"- **Cores**: {machine_info.get('cpu_cores', 'unknown')}\\n\")\n        f.write(f\"- **Memory**: {machine_info.get('memory_gb', 'unknown')} GB\\n\")\n        f.write(\"\\n\")\n\n        # Results summary\n        f.write(\"## Results Summary\\n\\n\")\n\n        successful = sum(1 for r in results if r.get(\"success\"))\n        f.write(f\"- **Benchmarks run**: {len(results)}\\n\")\n        f.write(f\"- **Successful**: {successful}\\n\")\n        f.write(f\"- **Failed**: {len(results) - successful}\\n\\n\")\n\n        # Per-suite results\n        if not df.empty:\n            for suite in df[\"suite\"].unique():\n                f.write(f\"### {suite}\\n\\n\")\n\n                suite_df = df[df[\"suite\"] == suite].sort_values(\"real_time\")\n                f.write(\"| Benchmark | Time | Unit | Iterations |\\n\")\n                f.write(\"|-----------|------|------|------------|\\n\")\n\n                for _, row in suite_df.iterrows():\n                    f.write(\n                        f\"| {row['name']} | {row['real_time']:.2f} | \"\n                        f\"{row['time_unit']} | {row['iterations']} |\\n\"\n                    )\n\n                f.write(\"\\n\")\n\n                # Link to chart if it exists\n                chart_path = f\"{suite}_chart.png\"\n                f.write(f\"![{suite} results]({chart_path})\\n\\n\")\n\n        # Failures\n        failures = [r for r in results if not r.get(\"success\")]\n        if failures:\n            f.write(\"## Failures\\n\\n\")\n            for fail in failures:\n                f.write(f\"### {fail['name']}\\n\\n\")\n                f.write(f\"```\\n{fail.get('error', 'Unknown error')}\\n```\\n\\n\")\n\n    print(f\"Generated report: {report_path}\")\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Run dispenso benchmarks\")\n    parser.add_argument(\n        \"--build-dir\",\n        \"-b\",\n        type=Path,\n        default=Path(\"build\"),\n        help=\"Build directory containing benchmark executables\",\n    )\n    parser.add_argument(\n        \"--output-dir\",\n        \"-o\",\n        type=Path,\n        default=Path(\"benchmark_results\"),\n        help=\"Output directory for results and charts\",\n    )\n    parser.add_argument(\n        \"--benchmarks\",\n        \"-B\",\n        type=str,\n        default=None,\n        help=\"Regex pattern to filter benchmarks\",\n    )\n    parser.add_argument(\n        \"--json-only\",\n        action=\"store_true\",\n        help=\"Only output JSON, skip chart generation\",\n    )\n\n    args = parser.parse_args()\n\n    # Gather machine info\n    print(\"Gathering machine information...\")\n    machine_info = get_machine_info()\n    print(f\"  CPU: {machine_info.get('cpu_model', 'unknown')}\")\n    print(f\"  Cores: {machine_info.get('cpu_cores', 'unknown')}\")\n    print(f\"  Memory: {machine_info.get('memory_gb', 'unknown')} GB\")\n    print()\n\n    # Find benchmarks\n    benchmarks = find_benchmarks(args.build_dir, args.benchmarks)\n    if not benchmarks:\n        print(f\"No benchmarks found in {args.build_dir}\")\n        print(\"Make sure you've built with -DDISPENSO_BUILD_BENCHMARKS=ON\")\n        sys.exit(1)\n\n    print(f\"Found {len(benchmarks)} benchmark(s):\")\n    for b in benchmarks:\n        print(f\"  - {b.name}\")\n    print()\n\n    # Run benchmarks\n    results = []\n    for benchmark in benchmarks:\n        result = run_benchmark(benchmark)\n        results.append(result)\n        if result[\"success\"]:\n            print(f\"  ✓ {benchmark.name}\")\n        else:\n            print(f\"  ✗ {benchmark.name}: {result.get('error', 'unknown error')[:50]}\")\n\n    # Save raw results\n    args.output_dir.mkdir(parents=True, exist_ok=True)\n\n    output_data = {\n        \"machine_info\": machine_info,\n        \"results\": results,\n    }\n\n    json_path = args.output_dir / \"benchmark_results.json\"\n    with open(json_path, \"w\") as f:\n        json.dump(output_data, f, indent=2, default=str)\n    print(f\"\\nSaved raw results to: {json_path}\")\n\n    # Generate charts and report\n    if not args.json_only and HAS_PLOTTING:\n        df = extract_benchmark_data(results)\n        if not df.empty:\n            generate_charts(df, args.output_dir)\n            generate_markdown_report(machine_info, results, df, args.output_dir)\n        else:\n            print(\n                \"No benchmark data to plot (benchmarks may not use google benchmark format)\"\n            )\n    elif not args.json_only and not HAS_PLOTTING:\n        print(\"Warning: matplotlib/pandas not available. Charts will not be generated.\")\n        print(\"Install with: pip install matplotlib pandas\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "benchmarks/rw_lock_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This benchmark relies on shared_lock from C++17\n#if __cplusplus >= 201703L\n\n#include <dispenso/rw_lock.h>\n\n#include <map>\n\n#include <shared_mutex>\n\n#include <dispenso/task_set.h>\n\n#include \"thread_benchmark_common.h\"\n\nconstexpr size_t kNumValues = 1 << 20;\n\n// Precondition: Start < writePeriod.  Note that this is enforced in BM_serial and BM_parallel\ntemplate <typename MtxType>\nint64_t iterate(MtxType& mtx, std::vector<int64_t>& values, int start, int writePeriod) {\n  int64_t total = 0;\n  int w = start;\n  for (auto& p : values) {\n    if (w++ == writePeriod) {\n      std::lock_guard<MtxType> lk(mtx);\n      ++p;\n      w = 0;\n    } else {\n      std::shared_lock<MtxType> lk(mtx);\n      total += p;\n    }\n  }\n  return total;\n}\n\nstruct NopMutex {\n  void lock() {}\n  void unlock() {}\n  void lock_shared() {}\n  void unlock_shared() {}\n};\n\ntemplate <typename MutexT>\nvoid BM_serial(benchmark::State& state) {\n  int writePeriod = state.range(0);\n  std::vector<int64_t> values(kNumValues);\n  int64_t total = 0;\n  MutexT mtx;\n  int start = 0;\n  for (auto UNUSED_VAR : state) {\n    total += iterate(mtx, values, start++, writePeriod);\n    if (start == writePeriod) {\n      start = 0;\n    }\n  }\n\n  benchmark::DoNotOptimize(total);\n}\n\nstatic void CustomArgumentsSerial(benchmark::internal::Benchmark* b) {\n  for (int j : {2, 8, 32, 128, 512}) {\n    b->Args({j});\n  }\n}\n\ntemplate <typename MutexT>\nvoid BM_parallel(benchmark::State& state) {\n  int concurrency = state.range(0);\n  int writePeriod = state.range(1);\n  std::vector<int64_t> values(kNumValues);\n  std::atomic<int64_t> total(0);\n  MutexT mtx;\n  int start = 0;\n\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n  for (auto UNUSED_VAR : state) {\n    for (int c = 0; c < concurrency; ++c) {\n      tasks.schedule([&total, start, &mtx, &values, writePeriod]() {\n        total.fetch_add(iterate(mtx, values, start, writePeriod), std::memory_order_acq_rel);\n      });\n      if (++start == writePeriod) {\n        start = 0;\n      }\n    }\n    tasks.wait();\n  }\n\n  benchmark::DoNotOptimize(total.load(std::memory_order_acquire));\n}\n\nstatic void CustomArgumentsParallel(benchmark::internal::Benchmark* b) {\n  for (int j : {2, 8, 32, 128, 512}) {\n    for (int s : {1, 2, 4, 8, 16, 32}) {\n      if (s > static_cast<int>(std::thread::hardware_concurrency())) {\n        break;\n      }\n      b->Args({s, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, NopMutex)->Apply(CustomArgumentsSerial)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_serial, std::shared_mutex)->Apply(CustomArgumentsSerial)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_serial, dispenso::RWLock)->Apply(CustomArgumentsSerial)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_parallel, std::shared_mutex)->Apply(CustomArgumentsParallel)->UseRealTime();\n\nBENCHMARK_TEMPLATE(BM_parallel, dispenso::RWLock)->Apply(CustomArgumentsParallel)->UseRealTime();\n\n#endif // C++17\n"
  },
  {
    "path": "benchmarks/simple_for_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#include <unordered_map>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_for.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include <taskflow/taskflow.hpp>\n#if TF_VERSION > 300000\n#include <taskflow/algorithm/for_each.hpp>\n#endif // TF_VERSION\n\n#include \"thread_benchmark_common.h\"\n\nstatic uint32_t kSeed(8);\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 1000000;\nstatic constexpr int kLargeSize = 100000000;\n\nstatic constexpr uint32_t kMinSizePerChunk = 10000;\n\nconst std::vector<int>& getInputs(int num_elements) {\n  static std::unordered_map<int, std::vector<int>> vecs;\n  auto it = vecs.find(num_elements);\n  if (it != vecs.end()) {\n    return it->second;\n  }\n  // No need to use a high-quality rng for this test.\n  srand(kSeed);\n  std::vector<int> values;\n  values.reserve(num_elements);\n  for (int i = 0; i < num_elements; ++i) {\n    values.push_back((rand() & 255) - 127);\n  }\n  auto res = vecs.emplace(num_elements, std::move(values));\n  assert(res.second);\n  return res.first->second;\n}\n\ntemplate <int num_elements>\nvoid BM_serial(benchmark::State& state) {\n  std::vector<int> output(num_elements, 0);\n  auto& input = getInputs(num_elements);\n\n  for (auto UNUSED_VAR : state) {\n    for (size_t i = 0; i < num_elements; ++i) {\n      output[i] = input[i] * input[i] - 3 * input[i];\n    }\n  }\n}\n\nvoid checkResults(const std::vector<int>& input, const std::vector<int>& output) {\n  for (size_t i = 0; i < input.size(); ++i) {\n    if (output[i] != input[i] * input[i] - 3 * input[i]) {\n      std::cerr << \"FAIL! \" << output[i] << \" vs \" << input[i] * input[i] - 3 * input[i]\n                << std::endl;\n      abort();\n    }\n  }\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  dispenso::ThreadPool pool(num_threads);\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = kMinSizePerChunk;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    dispenso::parallel_for(\n        tasks,\n        0,\n        num_elements,\n        [&input, &output](size_t i) { output[i] = input[i] * input[i] - 3 * input[i]; },\n        options);\n  }\n  checkResults(input, output);\n}\n\nvoid BM_taskflow(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  auto& input = getInputs(num_elements);\n\n  tf::Executor executor(num_threads);\n  tf::Taskflow taskflow;\n\n  for (auto UNUSED_VAR : state) {\n    taskflow.for_each_index(0, num_elements, 1, [&input, &output](int i) {\n      output[i] = input[i] * input[i] - 3 * input[i];\n    });\n    executor.run(taskflow).wait();\n  }\n  checkResults(input, output);\n}\n\nvoid BM_dispenso_static_chunk(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  dispenso::ThreadPool pool(num_threads);\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = kMinSizePerChunk;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    auto range = dispenso::makeChunkedRange(0, num_elements, dispenso::ParForChunking::kStatic);\n    dispenso::parallel_for(\n        tasks,\n        range,\n        [&input, &output](size_t begin, size_t end) {\n          for (size_t i = begin; i < end; ++i) {\n            output[i] = input[i] * input[i] - 3 * input[i];\n          }\n        },\n        options);\n  }\n  checkResults(input, output);\n}\n\nvoid BM_dispenso_auto_chunk(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  dispenso::ThreadPool pool(num_threads);\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = kMinSizePerChunk;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    auto range = dispenso::makeChunkedRange(0, num_elements, dispenso::ParForChunking::kAuto);\n    dispenso::parallel_for(\n        tasks,\n        range,\n        [&input, &output](size_t begin, size_t end) {\n          for (size_t i = begin; i < end; ++i) {\n            output[i] = input[i] * input[i] - 3 * input[i];\n          }\n        },\n        options);\n  }\n  checkResults(input, output);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n  omp_set_num_threads(num_threads);\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n#pragma omp parallel for\n    for (int i = 0; i < num_elements; ++i) {\n      output[i] = input[i] * input[i] - 3 * input[i];\n    }\n  }\n  checkResults(input, output);\n}\n#endif /*defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  std::vector<int> output(num_elements, 0);\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(num_threads);\n\n    tbb::parallel_for(\n        tbb::blocked_range<size_t>(0, num_elements),\n        [&input, &output](const tbb::blocked_range<size_t>& r) {\n          for (size_t i = r.begin(); i < r.end(); ++i) {\n            output[i] = input[i] * input[i] - 3 * input[i];\n          }\n        });\n  }\n  checkResults(input, output);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif // OPENMP\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\nBENCHMARK(BM_taskflow)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_static_chunk)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_auto_chunk)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/simple_pool_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Basic thread pool benchmarks comparing dispenso, TBB, and Folly.\n * Tests simple task scheduling throughput.\n */\n\n#include <dispenso/task_set.h>\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include <tbb/task_group.h>\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\n#include <folly/VirtualExecutor.h>\n#include <folly/executors/CPUThreadPoolExecutor.h>\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\n#include \"thread_benchmark_common.h\"\n\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 10000;\nstatic constexpr int kLargeSize = 1000000;\n\nstruct alignas(64) Work {\n  size_t count = 0;\n\n  void operator+=(size_t o) {\n    count += o;\n  }\n};\n\nWork g_work[1025];\nstd::atomic<int> g_tCounter{0};\ninline int testTid() {\n  static DISPENSO_THREAD_LOCAL int t = -1;\n  if (t < 0) {\n    t = g_tCounter.fetch_add(1, std::memory_order_acq_rel);\n  }\n  return t;\n}\n\ninline Work& work() {\n  static DISPENSO_THREAD_LOCAL Work* w = nullptr;\n\n  if (!w) {\n    if (testTid() == 0) {\n      w = g_work + 1024;\n    } else {\n      w = g_work + (testTid() & 1023);\n    }\n  }\n  return *w;\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n  dispenso::ThreadPool pool(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    for (int i = 0; i < num_elements; ++i) {\n      tasks.schedule([i]() { work() += i; });\n    }\n  }\n}\n\nvoid BM_dispenso_bulk(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n  dispenso::ThreadPool pool(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n    tasks.scheduleBulk(\n        static_cast<size_t>(num_elements), [](size_t i) { return [i]() { work() += i; }; });\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n  tbb_compat::task_scheduler_init initsched(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    tbb::task_group g;\n    for (int i = 0; i < num_elements; ++i) {\n      g.run([i]() { work() += i; });\n    }\n    g.wait();\n  }\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nvoid BM_folly(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n  folly::CPUThreadPoolExecutor follyExec(num_threads);\n\n  for (auto UNUSED_VAR : state) {\n    folly::VirtualExecutor tasks(&follyExec);\n    for (int i = 0; i < num_elements; ++i) {\n      tasks.add([i]() { work() += i; });\n    }\n  }\n}\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int s : pow2HalfStepThreads()) {\n      b->Args({s, j});\n    }\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nBENCHMARK(BM_folly)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\nBENCHMARK(BM_dispenso_bulk)->Apply(CustomArguments)->Unit(benchmark::kMicrosecond)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/small_buffer_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/small_buffer_allocator.h>\n\n#include \"benchmark_common.h\"\n\nconstexpr size_t kSmallSize = 32;\nconstexpr size_t kMediumSize = 128;\nconstexpr size_t kLargeSize = 256;\n\ntemplate <typename Alloc, typename Free>\nvoid run(benchmark::State& state, Alloc alloc, Free dealloc) {\n  std::vector<char*> ptrs(state.range(0));\n  for (auto UNUSED_VAR : state) {\n    for (char*& p : ptrs) {\n      p = alloc();\n    }\n    for (char* p : ptrs) {\n      dealloc(p);\n    }\n  }\n}\n\ntemplate <size_t kSize>\nvoid BM_newdelete(benchmark::State& state) {\n  run(state, []() { return new char[kSize]; }, [](char* buf) { delete[] (buf); });\n}\n\ntemplate <size_t kSize>\nvoid BM_small_buffer_allocator(benchmark::State& state) {\n  run(\n      state,\n      []() { return dispenso::allocSmallBuffer<kSize>(); },\n      [](char* buf) { dispenso::deallocSmallBuffer<kSize>(buf); });\n}\n\nBENCHMARK_TEMPLATE(BM_newdelete, kSmallSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kSmallSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_newdelete, kMediumSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kMediumSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_newdelete, kLargeSize)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kLargeSize)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_newdelete, kSmallSize)->Threads(16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kSmallSize)->Threads(16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_newdelete, kMediumSize)->Threads(16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kMediumSize)->Threads(16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_TEMPLATE(BM_newdelete, kLargeSize)->Threads(16)->Range(1 << 13, 1 << 15);\nBENCHMARK_TEMPLATE(BM_small_buffer_allocator, kLargeSize)->Threads(16)->Range(1 << 13, 1 << 15);\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/summing_for_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <unordered_map>\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_reduce.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nstatic uint32_t kSeed(8);\nstatic constexpr int kSmallSize = 1000;\nstatic constexpr int kMediumSize = 1000000;\nstatic constexpr int kLargeSize = 100000000;\n\nconst std::vector<int>& getInputs(int num_elements) {\n  static std::unordered_map<int, std::vector<int>> vecs;\n  auto it = vecs.find(num_elements);\n  if (it != vecs.end()) {\n    return it->second;\n  }\n  // No need to use a high-quality rng for this test.\n  srand(kSeed);\n  std::vector<int> values;\n  values.reserve(num_elements);\n  for (int i = 0; i < num_elements; ++i) {\n    values.push_back((rand() & 255) - 127);\n  }\n  auto res = vecs.emplace(num_elements, std::move(values));\n  assert(res.second);\n  return res.first->second;\n}\n\nvoid checkResults(const std::vector<int>& inputs, int64_t actual, int foo) {\n  int64_t expected = 0;\n  for (auto v : inputs) {\n    expected += v * v - 3 * foo * v;\n  }\n  if (expected != actual) {\n    std::cerr << \"FAIL! \" << expected << \" vs \" << actual << std::endl;\n    abort();\n  }\n}\n\ntemplate <int num_elements>\nvoid BM_serial(benchmark::State& state) {\n  auto& input = getInputs(num_elements);\n  int64_t sum = 0;\n  int foo = 0;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n    for (size_t i = 0; i < num_elements; ++i) {\n      sum += input[i] * input[i] - 3 * foo * input[i];\n    }\n  }\n  checkResults(input, sum, foo);\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  int64_t sum = 0;\n  int foo = 0;\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = 50000;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n\n    std::vector<int64_t> sums;\n    sums.reserve(num_threads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        tasks,\n        sums,\n        []() { return int64_t{0}; },\n        dispenso::makeChunkedRange(0, num_elements, dispenso::ParForChunking::kAuto),\n        [&input, foo](int64_t& lsumStore, size_t i, size_t end) {\n          int64_t lsum = 0;\n          for (; i != end; ++i) {\n            lsum += input[i] * input[i] - 3 * foo * input[i];\n          }\n          lsumStore += lsum;\n        },\n        options);\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  omp_set_num_threads(num_threads);\n\n  int64_t sum = 0;\n\n  int foo = 0;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n#pragma omp parallel for reduction(+ : sum)\n    for (int i = 0; i < num_elements; ++i) {\n      sum += input[i] * input[i] - 3 * foo * input[i];\n    }\n  }\n  checkResults(input, sum, foo);\n}\n#endif /*defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  int64_t sum = 0;\n\n  int foo = 0;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(num_threads);\n    ++foo;\n    sum = tbb::parallel_reduce(\n        tbb::blocked_range<const int*>(&input[0], &input[0] + num_elements),\n        int64_t{0},\n        [foo](const tbb::blocked_range<const int*>& r, int64_t init) -> int64_t {\n          for (const int* a = r.begin(); a != r.end(); ++a)\n            init += *a * *a - 3 * foo * *a;\n          return init;\n        },\n        [](int64_t x, int64_t y) -> int64_t { return x + y; });\n  }\n  checkResults(input, sum, foo);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_static(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  int64_t sum = 0;\n  int foo = 0;\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = 50000;\n\n  auto& input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n\n    std::vector<int64_t> sums;\n    sums.reserve(num_threads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        tasks,\n        sums,\n        []() { return int64_t{0}; },\n        dispenso::makeChunkedRange(0, num_elements, dispenso::ParForChunking::kStatic),\n        [&input, foo](int64_t& lsumStore, size_t i, size_t end) {\n          int64_t lsum = 0;\n          for (; i != end; ++i) {\n            lsum += input[i] * input[i] - 3 * foo * input[i];\n          }\n          lsumStore += lsum;\n        },\n        options);\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo);\n}\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif // OPENMP\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_static)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "benchmarks/tbb_compat.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n/**\n * TBB compatibility header for supporting both legacy TBB and oneTBB (2021+).\n *\n * oneTBB 2021+ removed task_scheduler_init in favor of global_control and task_arena.\n * oneTBB also changed pipeline.h to parallel_pipeline.h and renamed filter types.\n * This header provides a unified interface that works with both versions.\n */\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n\n// Include version header to detect TBB version\n#if __has_include(<tbb/version.h>)\n#include <tbb/version.h>\n#elif __has_include(<tbb/tbb_stddef.h>)\n#include <tbb/tbb_stddef.h>\n#endif\n\n// Detect oneTBB (2021+) vs legacy TBB\n#if defined(TBB_VERSION_MAJOR) && TBB_VERSION_MAJOR >= 2021\n#define TBB_USE_ONETBB 1\n#else\n#define TBB_USE_ONETBB 0\n#endif\n\n#if TBB_USE_ONETBB\n// oneTBB 2021+ uses global_control instead of task_scheduler_init\n#include <tbb/global_control.h>\n#include <tbb/parallel_pipeline.h>\n#include <tbb/task_arena.h>\n#include <tbb/task_group.h>\n\nnamespace tbb_compat {\n\n// RAII wrapper for thread count control, compatible with old task_scheduler_init API\nclass task_scheduler_init {\n public:\n  explicit task_scheduler_init(int num_threads)\n      : control_(tbb::global_control::max_allowed_parallelism, num_threads) {}\n\n private:\n  tbb::global_control control_;\n};\n\n// Pipeline filter mode compatibility\n// In oneTBB, tbb::filter::serial -> tbb::filter_mode::serial_in_order\n// In oneTBB, tbb::filter::parallel -> tbb::filter_mode::parallel\nnamespace filter {\nconstexpr auto serial = tbb::filter_mode::serial_in_order;\nconstexpr auto parallel = tbb::filter_mode::parallel;\n} // namespace filter\n\n} // namespace tbb_compat\n\n#else\n// Legacy TBB (< 2021)\n#include <tbb/pipeline.h>\n#include <tbb/task_group.h>\n#include <tbb/task_scheduler_init.h>\n\nnamespace tbb_compat {\n\nusing task_scheduler_init = tbb::task_scheduler_init;\n\n// Pipeline filter mode compatibility - just alias the legacy types\nnamespace filter {\nconstexpr auto serial = tbb::filter::serial;\nconstexpr auto parallel = tbb::filter::parallel;\n} // namespace filter\n\n} // namespace tbb_compat\n\n#endif // TBB_USE_ONETBB\n\n#endif // !BENCHMARK_WITHOUT_TBB\n"
  },
  {
    "path": "benchmarks/thread_benchmark_common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#ifdef _POSIX_C_SOURCE\n#include <sys/resource.h>\n#endif // _POSIX_C_SOURCE\n\n#include <cmath>\n#include <iostream>\n#include <thread>\n\n#include \"benchmark_common.h\"\n\ninline std::vector<int> pow2HalfStepThreads() {\n  const int kRunningThreads = std::thread::hardware_concurrency();\n  std::vector<int> result;\n  result.push_back(1);\n  for (int block = 2; block <= kRunningThreads; block *= 2) {\n    int step = block / 2;\n\n    for (int i = block; i < 2 * block && i <= kRunningThreads; i += step) {\n      result.push_back(i);\n    }\n  }\n  return result;\n}\n\n#if defined(_POSIX_C_SOURCE) || defined(__MACH__)\nstruct rusage g_rusage;\n\ninline void startRusage() {\n  std::atomic_thread_fence(std::memory_order_acquire);\n  getrusage(RUSAGE_SELF, &g_rusage);\n  std::atomic_thread_fence(std::memory_order_release);\n}\n\ninline double duration(struct timeval start, struct timeval end) {\n  return (end.tv_sec + 1e-6 * end.tv_usec) - (start.tv_sec + 1e-6 * start.tv_usec);\n}\n\ninline void endRusage(benchmark::State& state) {\n  std::atomic_thread_fence(std::memory_order_acquire);\n  struct rusage res;\n  getrusage(RUSAGE_SELF, &res);\n  std::atomic_thread_fence(std::memory_order_release);\n\n  double userTime = duration(g_rusage.ru_utime, res.ru_utime);\n  double sysTime = duration(g_rusage.ru_stime, res.ru_stime);\n\n  state.counters[\"\\t0 User\"] = userTime;\n  state.counters[\"\\t1 System\"] = sysTime;\n}\n#else\ninline void startRusage() {}\ninline void endRusage(benchmark::State& state) {}\n#endif //_POSIX_C_SOURCE\n\ninline double getMean(const std::vector<double>& data) {\n  double sum = 0.0;\n  for (auto d : data) {\n    sum += d;\n  }\n  return sum / data.size();\n}\n\ninline double getStddev(double mean, const std::vector<double>& data) {\n  double sumsq = 0.0;\n  for (auto d : data) {\n    auto dev = mean - d;\n    sumsq += dev * dev;\n  }\n  return std::sqrt(sumsq / data.size());\n}\n\nvoid doStats(const std::vector<double>& times, benchmark::State& state) {\n  double mean = getMean(times);\n  state.counters[\"mean\"] = mean;\n  state.counters[\"stddev\"] = getStddev(mean, times);\n}\n"
  },
  {
    "path": "benchmarks/timed_task_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/timed_task.h>\n\n#include <deque>\n\n#include <dispenso/completion_event.h>\n#include <dispenso/schedulable.h>\n#include \"thread_benchmark_common.h\"\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\n#include <folly/executors/FunctionScheduler.h>\n#include <folly/synchronization/Baton.h>\n#endif // !BENCHMARK_WITHOUT_FOLLY\n\nsize_t getIterations() {\n  // If we want to get a sense of system overhead via getrusage, we need to boost things into the\n  // milliseconds range to get any kind of reasonable values.  Typically on Linux I'm seeing that\n  // Folly uses slightly more resources (system + user) on average, but that dispenso uses more in\n  // the worst cases.  The very worst case is still less than 1% of 1 cpu (~8 seconds active,\n  // 50ms of system+user time).\n  static const bool itersEnv = getenv(\"TEST_WITH_MANY_ITERS\") != nullptr;\n  if (itersEnv) {\n    return 2000;\n  } else {\n    return 200;\n  }\n}\n\nvoid absTimesToErrors(std::vector<double>& times, double prevTime, double expectedDelta) {\n  for (size_t i = 0; i < times.size(); ++i) {\n    auto temp = times[i];\n    times[i] -= prevTime;\n    times[i] -= expectedDelta;\n    times[i] = std::abs(times[i]);\n    prevTime = temp;\n  }\n}\n\nvoid absTimesToSteadyErrors(std::vector<double>& times, double prevTime, double expectedDelta) {\n  for (size_t i = 0; i < times.size(); ++i) {\n    times[i] -= prevTime;\n    times[i] -= expectedDelta;\n    times[i] = std::abs(times[i]);\n    prevTime += expectedDelta;\n  }\n}\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\ntemplate <size_t kInMs, bool kSteady>\nvoid BM_folly(benchmark::State& state) {\n  std::vector<double> times(getIterations());\n  std::atomic<size_t> count(0);\n  startRusage();\n  folly::FunctionScheduler fs;\n  if (kSteady) {\n    fs.setSteady(true);\n  }\n  folly::Baton fin;\n  fs.addFunction(\n      [&] {\n        auto cur = count.fetch_add(1, std::memory_order_acq_rel);\n        if (cur < times.size()) {\n          times[cur] = dispenso::getTime();\n        } else if (cur == times.size()) {\n          fin.post();\n        }\n      },\n      std::chrono::milliseconds(kInMs),\n      \"add\");\n  double prevTime = dispenso::getTime();\n  fs.start();\n  fin.wait();\n  fs.shutdown();\n\n  for (auto UNUSED_VAR : state) {\n    // dummy iteration\n    state.SetIterationTime(0.1);\n  }\n\n  if (kSteady) {\n    // We need to adjust prevTime because for steady scheduling, folly tries to schedule right away.\n    absTimesToSteadyErrors(times, prevTime - kInMs * 1e-3, kInMs * 1e-3);\n  } else {\n    absTimesToErrors(times, prevTime, kInMs * 1e-3);\n  }\n  endRusage(state);\n\n  doStats(times, state);\n}\n\nstruct FollyItem {\n  std::vector<double> times;\n  std::atomic<size_t> count{0};\n  size_t millis;\n  folly::Baton<true, std::atomic> fin;\n\n  FollyItem() : times(getIterations()) {}\n};\n\ntemplate <bool kSteady>\nvoid BM_folly_mixed(benchmark::State& state) {\n  FollyItem items[3];\n\n  items[0].millis = 1;\n  items[1].millis = 4;\n  items[2].millis = 3;\n\n  startRusage();\n  folly::FunctionScheduler fs;\n  if (kSteady) {\n    fs.setSteady(true);\n  }\n\n  auto doSchedule = [&fs](FollyItem& fitem, const char* name) {\n    fs.addFunction(\n        [&] {\n          auto cur = fitem.count.fetch_add(1, std::memory_order_acq_rel);\n          if (cur < fitem.times.size()) {\n            fitem.times[cur] = dispenso::getTime();\n          } else if (cur == fitem.times.size()) {\n            fitem.fin.post();\n          }\n        },\n        std::chrono::milliseconds(fitem.millis),\n        name);\n  };\n\n  size_t i = 0;\n  for (auto name : {\"a\", \"b\", \"c\"}) {\n    doSchedule(items[i++], name);\n  }\n\n  double prevTime = dispenso::getTime();\n  fs.start();\n  for (auto& item : items) {\n    item.fin.wait();\n  }\n  fs.shutdown();\n\n  for (auto UNUSED_VAR : state) {\n    // dummy iteration\n    state.SetIterationTime(0.1);\n  }\n\n  if (kSteady) {\n    // We need to adjust prevTime because for steady scheduling, folly tries to schedule right away.\n    for (auto& item : items) {\n      absTimesToSteadyErrors(item.times, prevTime - item.millis * 1e-3, item.millis * 1e-3);\n    }\n  } else {\n    for (auto& item : items) {\n      absTimesToErrors(item.times, prevTime, item.millis * 1e-3);\n    }\n  }\n  endRusage(state);\n\n  // append all times\n  items[0].times.insert(items[0].times.end(), items[1].times.begin(), items[1].times.end());\n  items[0].times.insert(items[0].times.end(), items[2].times.begin(), items[2].times.end());\n\n  doStats(items[0].times, state);\n}\n\n#endif\n\ndispenso::TimedTaskScheduler& getScheduler() {\n  static const bool rtEnv = getenv(\"TEST_WITH_REALTIME\") != nullptr;\n  if (rtEnv) {\n    static dispenso::TimedTaskScheduler sched(dispenso::ThreadPriority::kRealtime);\n    return sched;\n  } else {\n    return dispenso::globalTimedTaskScheduler();\n  }\n}\n\ntemplate <size_t kInMs, bool kSteady>\nvoid BM_dispenso(benchmark::State& state) {\n  std::vector<double> times(getIterations());\n  std::atomic<size_t> count(0);\n\n  double period = 1e-3 * kInMs;\n\n  startRusage();\n  dispenso::CompletionEvent fin;\n  double prevTime = dispenso::getTime();\n\n  auto type = kSteady ? dispenso::TimedTaskType::kSteady : dispenso::TimedTaskType::kNormal;\n\n  auto task = getScheduler().schedule(\n      dispenso::kImmediateInvoker,\n      [&] {\n        auto cur = count.fetch_add(1, std::memory_order_acq_rel);\n        if (cur < times.size()) {\n          times[cur] = dispenso::getTime();\n        }\n        if (cur + 1 == times.size()) {\n          fin.notify();\n          return false;\n        }\n        return true;\n      },\n      prevTime + period,\n      period,\n      times.size(),\n      type);\n  fin.wait();\n\n  for (auto UNUSED_VAR : state) {\n    // dummy iteration\n    state.SetIterationTime(0.1);\n  }\n\n  if (kSteady) {\n    absTimesToSteadyErrors(times, prevTime, kInMs * 1e-3);\n\n  } else {\n    absTimesToErrors(times, prevTime, kInMs * 1e-3);\n  }\n  endRusage(state);\n\n  doStats(times, state);\n}\n\nstruct DispensoItem {\n  std::vector<double> times;\n  std::atomic<size_t> count{0};\n  size_t millis;\n  dispenso::CompletionEvent fin;\n  DispensoItem() : times(getIterations()) {}\n};\n\ntemplate <bool kSteady>\nvoid BM_dispenso_mixed(benchmark::State& state) {\n  DispensoItem items[3];\n  std::deque<dispenso::TimedTask> tasks;\n\n  items[0].millis = 1;\n  items[1].millis = 4;\n  items[2].millis = 3;\n\n  startRusage();\n  double prevTime = dispenso::getTime();\n  auto type = kSteady ? dispenso::TimedTaskType::kSteady : dispenso::TimedTaskType::kNormal;\n  auto doSchedule = [&](DispensoItem& ditem) {\n    double period = 1e-3 * ditem.millis;\n\n    tasks.push_back(\n        getScheduler().schedule(\n            dispenso::kImmediateInvoker,\n            [&] {\n              auto cur = ditem.count.fetch_add(1, std::memory_order_acq_rel);\n              if (cur < ditem.times.size()) {\n                ditem.times[cur] = dispenso::getTime();\n              }\n              if (cur + 1 == ditem.times.size()) {\n                ditem.fin.notify();\n                return false;\n              }\n              return true;\n            },\n            prevTime + period,\n            period,\n            ditem.times.size(),\n            type));\n  };\n\n  for (size_t i = 0; i < 3; ++i) {\n    doSchedule(items[i]);\n  }\n\n  for (auto& item : items) {\n    item.fin.wait();\n  }\n\n  for (auto UNUSED_VAR : state) {\n    // dummy iteration\n    state.SetIterationTime(0.1);\n  }\n\n  if (kSteady) {\n    for (auto& item : items) {\n      absTimesToSteadyErrors(item.times, prevTime, item.millis * 1e-3);\n    }\n  } else {\n    for (auto& item : items) {\n      absTimesToErrors(item.times, prevTime, item.millis * 1e-3);\n    }\n  }\n  endRusage(state);\n\n  // append all times\n  items[0].times.insert(items[0].times.end(), items[1].times.begin(), items[1].times.end());\n  items[0].times.insert(items[0].times.end(), items[2].times.begin(), items[2].times.end());\n\n  doStats(items[0].times, state);\n}\n\nBENCHMARK_TEMPLATE2(BM_dispenso, 2, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_dispenso, 4, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_dispenso, 6, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_dispenso, 2, true)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_dispenso, 4, true)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_dispenso, 6, true)->UseManualTime();\n\nBENCHMARK_TEMPLATE(BM_dispenso_mixed, false)->UseManualTime();\nBENCHMARK_TEMPLATE(BM_dispenso_mixed, true)->UseManualTime();\n\n#if !defined(BENCHMARK_WITHOUT_FOLLY)\nBENCHMARK_TEMPLATE2(BM_folly, 2, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_folly, 4, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_folly, 6, false)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_folly, 2, true)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_folly, 4, true)->UseManualTime();\nBENCHMARK_TEMPLATE2(BM_folly, 6, true)->UseManualTime();\n\nBENCHMARK_TEMPLATE(BM_folly_mixed, false)->UseManualTime();\nBENCHMARK_TEMPLATE(BM_folly_mixed, true)->UseManualTime();\n#endif // FOLLY\n"
  },
  {
    "path": "benchmarks/trivial_compute_benchmark.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <cmath>\n\n#include <dispenso/parallel_for.h>\n\n#if defined(_OPENMP)\n#include <omp.h>\n#endif\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\n#include \"tbb/blocked_range.h\"\n#include \"tbb/parallel_reduce.h\"\n#include \"tbb_compat.h\"\n#endif // !BENCHMARK_WITHOUT_TBB\n\n#include \"thread_benchmark_common.h\"\n\nstatic constexpr int kSmallSize = 100;\nstatic constexpr int kMediumSize = 1000000;\nstatic constexpr int kLargeSize = 100000000;\n\nuint32_t getInputs(int num_elements) {\n  srand(num_elements);\n  return rand() & 127;\n}\n\ninline uint64_t calculate(uint64_t input, uint64_t index, size_t foo) {\n  return std::cos(\n      std::log(\n          std::sin(std::exp(std::sqrt(static_cast<double>((input ^ index) - 3 * foo * input))))));\n}\n\nvoid checkResults(uint32_t input, uint64_t actual, int foo, size_t num_elements) {\n  if (!foo)\n    return;\n  if (input != getInputs(num_elements)) {\n    std::cerr << \"Failed to recover input!\" << std::endl;\n    abort();\n  }\n  uint64_t expected = 0;\n  for (size_t i = 0; i < num_elements; ++i) {\n    expected += calculate(input, i, foo);\n  }\n  if (expected != actual) {\n    std::cerr << \"FAIL! \" << expected << \" vs \" << actual << std::endl;\n    abort();\n  }\n}\n\ntemplate <int num_elements>\nvoid BM_serial(benchmark::State& state) {\n  auto input = getInputs(num_elements);\n  uint64_t sum = 0;\n  int foo = 0;\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n    for (size_t i = 0; i < num_elements; ++i) {\n      sum += calculate(input, i, foo);\n    }\n  }\n  checkResults(input, sum, foo, num_elements);\n}\n\nvoid BM_dispenso(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  uint64_t sum = 0;\n  int foo = 0;\n\n  dispenso::ParForOptions options;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n  options.minItemsPerChunk = 4000;\n\n  auto input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n\n    std::vector<uint64_t> sums;\n    sums.reserve(num_threads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        tasks,\n        sums,\n        []() { return uint64_t{0}; },\n        0,\n        num_elements,\n        [input, foo](uint64_t& lsumStore, int i, int end) {\n          uint64_t lsum = 0;\n          for (; i != end; ++i) {\n            lsum += calculate(input, i, foo);\n          }\n          lsumStore += lsum;\n        },\n        options);\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo, num_elements);\n}\n\n#if defined(_OPENMP)\nvoid BM_omp(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  omp_set_num_threads(num_threads);\n\n  uint64_t sum = 0;\n\n  int foo = 0;\n\n  auto input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    sum = 0;\n    ++foo;\n#pragma omp parallel for reduction(+ : sum)\n    for (int i = 0; i < num_elements; ++i) {\n      sum += calculate(input, i, foo);\n    }\n  }\n  checkResults(input, sum, foo, num_elements);\n}\n#endif /* defined(_OPENMP)*/\n\n#if !defined(BENCHMARK_WITHOUT_TBB)\nvoid BM_tbb(benchmark::State& state) {\n  const int num_threads = state.range(0);\n  const int num_elements = state.range(1);\n\n  uint64_t sum = 0;\n\n  int foo = 0;\n\n  auto input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    tbb_compat::task_scheduler_init initsched(num_threads);\n    ++foo;\n    sum = tbb::parallel_reduce(\n        tbb::blocked_range<size_t>(0, num_elements),\n        uint64_t{0},\n        [input, foo](const tbb::blocked_range<size_t>& r, uint64_t init) -> uint64_t {\n          for (size_t a = r.begin(); a != r.end(); ++a)\n            init += calculate(input, a, foo);\n          return init;\n        },\n        [](uint64_t x, uint64_t y) -> uint64_t { return x + y; });\n  }\n  checkResults(input, sum, foo, num_elements);\n}\n#endif // !BENCHMARK_WITHOUT_TBB\n\nvoid BM_dispenso_static(benchmark::State& state) {\n  const int num_threads = state.range(0) - 1;\n  const int num_elements = state.range(1);\n\n  dispenso::ThreadPool pool(num_threads);\n\n  uint64_t sum = 0;\n  int foo = 0;\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = 4000;\n\n  auto input = getInputs(num_elements);\n  for (auto UNUSED_VAR : state) {\n    dispenso::TaskSet tasks(pool);\n\n    std::vector<uint64_t> sums;\n    sums.reserve(num_threads + 1);\n    ++foo;\n    dispenso::parallel_for(\n        tasks,\n        sums,\n        []() { return uint64_t{0}; },\n        dispenso::makeChunkedRange(0, num_elements, dispenso::ParForChunking::kStatic),\n        [input, foo](uint64_t& lsumStore, int i, int end) {\n          uint64_t lsum = 0;\n          for (; i != end; ++i) {\n            lsum += calculate(input, i, foo);\n          }\n          lsumStore += lsum;\n        },\n        options);\n    sum = 0;\n    for (auto s : sums) {\n      sum += s;\n    }\n  }\n\n  checkResults(input, sum, foo, num_elements);\n}\n\nstatic void CustomArguments(benchmark::internal::Benchmark* b) {\n  for (int j : {kSmallSize, kMediumSize, kLargeSize}) {\n    for (int i : pow2HalfStepThreads()) {\n      b->Args({i, j});\n    }\n  }\n}\n\nBENCHMARK_TEMPLATE(BM_serial, kSmallSize);\nBENCHMARK_TEMPLATE(BM_serial, kMediumSize);\nBENCHMARK_TEMPLATE(BM_serial, kLargeSize);\n\n#if defined(_OPENMP)\nBENCHMARK(BM_omp)->Apply(CustomArguments)->UseRealTime();\n#endif // OPENMP\n#if !defined(BENCHMARK_WITHOUT_TBB)\nBENCHMARK(BM_tbb)->Apply(CustomArguments)->UseRealTime();\n#endif // !BENCHMARK_WITHOUT_TBB\nBENCHMARK(BM_dispenso)->Apply(CustomArguments)->UseRealTime();\nBENCHMARK(BM_dispenso_static)->Apply(CustomArguments)->UseRealTime();\n\nBENCHMARK_MAIN();\n"
  },
  {
    "path": "cmake/DispensoConfig.cmake.in",
    "content": "# \n# Copyright (c) Meta Platforms, Inc. and affiliates.\n# \n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n#\n\n@PACKAGE_INIT@\n\ninclude(CMakeFindDependencyMacro)\n\nfind_dependency(Threads)\n\nif(@DISPENSO_USE_SYSTEM_CONCURRENTQUEUE@)\n  find_dependency(concurrentqueue)\nendif()\n\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@_Exports.cmake\")\n\ncheck_required_components(\"@PROJECT_NAME@\")\n"
  },
  {
    "path": "codecov.yml",
    "content": "# Codecov configuration for dispenso\n# See https://docs.codecov.com/docs/codecovyml-reference\n\ncoverage:\n  # Overall project coverage settings\n  status:\n    project:\n      default:\n        # Require at least 92% overall coverage\n        target: 92%\n    patch:\n      default:\n        # New code should have at least 80% coverage\n        target: 80%\n        # This is informational, not blocking\n        informational: true\n\n  # Round coverage to 1 decimal place\n  precision: 1\n\n# Ignore third-party code and test files\nignore:\n  - \"dispenso/third-party/**\"\n  - \"tests/**\"\n  - \"benchmarks/**\"\n\n# Comment settings for PRs\ncomment:\n  layout: \"reach,diff,flags,files\"\n  behavior: default\n  require_changes: true\n"
  },
  {
    "path": "dispenso/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.12)\n\nfile(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)\nfile(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS *.h)\n\nif(NOT DISPENSO_BUILD_FAST_MATH)\n  list(FILTER SOURCES EXCLUDE REGEX \"fast_math/\")\n  list(FILTER HEADERS EXCLUDE REGEX \"fast_math/\")\nendif()\n\nmessage(\"SOURCES:  ${SOURCES}\")\n\nif(DISPENSO_SHARED_LIB)\n  add_compile_definitions(DISPENSO_SHARED_LIB DISPENSO_LIB_EXPORT)\n  add_library(dispenso SHARED ${SOURCES} ${HEADERS})\n\n  target_compile_options(dispenso PRIVATE\n  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-fvisibility=hidden>\n  )\nelse()\n  add_library(dispenso STATIC ${SOURCES} ${HEADERS})\nendif()\n\ntarget_compile_options(dispenso PRIVATE\n  $<$<CXX_COMPILER_ID:MSVC>:/W3 /WX>\n  # GCC false positive: stringop-overflow through deeply inlined atomics.\n  # Seen with GCC 13 on Linux and GCC 14 on macOS ARM64.\n  $<$<CXX_COMPILER_ID:GNU>:-Wno-stringop-overflow>\n  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion -Werror>\n)\n\nif(WIN32)\n  target_compile_definitions(dispenso PUBLIC NOMINMAX)\nendif()\n\ntarget_include_directories(dispenso\nPUBLIC\n  $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/..>\n  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>\n  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>\n)\n\nif(DISPENSO_USE_SYSTEM_CONCURRENTQUEUE)\n  find_package(concurrentqueue CONFIG REQUIRED)\n  target_link_libraries(dispenso PUBLIC concurrentqueue::concurrentqueue)\nelse()\n  target_include_directories(dispenso\n  PUBLIC\n    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/third-party>\n    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/dispenso/third-party>\n  )\nendif()\n\n# Export the C++ standard requirement so downstream consumers compile with at\n# least the same standard dispenso was built with (default: C++14).\ntarget_compile_features(dispenso PUBLIC cxx_std_${CMAKE_CXX_STANDARD})\n\nset(CMAKE_THREAD_PREFER_PTHREAD TRUE)\nset(THREADS_PREFER_PTHREAD_FLAG TRUE)\nfind_package(Threads REQUIRED)\ntarget_link_libraries(dispenso PUBLIC Threads::Threads)\n\ncheck_cxx_source_compiles(\"\n#include <atomic>\n#include <stdint.h>\nstd::atomic<int8_t> a(0);\nstd::atomic<int16_t> b(0);\nstd::atomic<int32_t> c(0);\nstd::atomic<int64_t> d(0);\nint main() {\n  ++a;\n  ++b;\n  ++c;\n  return ++d;\n}\n\" DISPENSO_HAS_ATOMIC_WITHOUT_LIB)\n\nif (NOT DISPENSO_HAS_ATOMIC_WITHOUT_LIB)\n  target_link_libraries(dispenso PUBLIC atomic)\nendif()\n\nif(WIN32)\n  target_link_libraries(dispenso PUBLIC Synchronization Winmm)\nendif()\n\nif (NOT DISPENSO_STANDALONE)\n  return()\nendif()\n\n## Install library ##\n\nset_target_properties(dispenso\n    PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})\n\ninstall(TARGETS dispenso\n  EXPORT ${PROJECT_NAME}_Exports\n  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\n    NAMELINK_SKIP\n  # on Windows put the dlls into bin\n  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n  # ... and the import lib into the devel package\n  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}\n)\n\ninstall(EXPORT ${PROJECT_NAME}_Exports\n  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}\n  NAMESPACE Dispenso::\n)\n\ninstall(TARGETS dispenso\n  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\n    NAMELINK_ONLY\n  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}\n)\n\n## Install headers ##\n\n# Build list of directory patterns to exclude from header installation.\nset(_dispenso_install_excludes \"\")\nif(NOT DISPENSO_BUILD_FAST_MATH)\n  list(APPEND _dispenso_install_excludes PATTERN \"fast_math\" EXCLUDE)\nendif()\nif(DISPENSO_USE_SYSTEM_CONCURRENTQUEUE)\n  list(APPEND _dispenso_install_excludes PATTERN \"third-party\" EXCLUDE)\nendif()\n\ninstall(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}\n  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}\n  FILES_MATCHING\n    PATTERN *.h\n    ${_dispenso_install_excludes}\n)\n\n## Generate and install CMake target exports ##\n\ninclude(CMakePackageConfigHelpers)\n\nconfigure_package_config_file(\n  \"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in\"\n  \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\"\nINSTALL_DESTINATION\n  ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}\n)\n\nwrite_basic_package_version_file(\n  \"${PROJECT_NAME}ConfigVersion.cmake\"\n  VERSION ${PROJECT_VERSION}\n  COMPATIBILITY SameMajorVersion\n)\n\ninstall(FILES\n  ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\n  ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\nDESTINATION\n  ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}\n)\n"
  },
  {
    "path": "dispenso/async_request.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file async_request.h\n * @ingroup group_async\n * A file providing AsyncRequest.  This is a bit like a lightweight channel for storing updates to\n * one object, mostly intended to be used as a single producer, single consumer update mechanism.\n **/\n\n#pragma once\n\n#if __cplusplus >= 201703L\n#include <optional>\n#else\n#include <dispenso/detail/op_result.h>\n#endif // C++17\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * A type for making async requests.  Although it is safe to use from multiple producers and\n * consumers, it is primarily intended to be used from single producer, single consumer.\n *\n * Typically the consumer will request an update of the value from thread 0, and the producer will\n * look whether an update was requested from thread 1.  Once the producer determines an update was\n * requested (updateRequested() returns true), it calls tryEmplaceUpdate() to update the underlying\n * data.  Then when the consumer on thread 0 next calls getUpdate(), an optional wrapper to the\n * updated data is returned, and the AsyncRequest object is reset (it no longer has valid data, and\n * no update will have yet been requested for the next update).\n **/\ntemplate <typename T>\nclass AsyncRequest {\n public:\n  // A lightweight std::optional-like type with a subset of functionality.\n#if __cplusplus >= 201703L\n  using OpResult = std::optional<T>;\n#else\n  using OpResult = detail::OpResult<T>;\n#endif // C++17\n\n  /**\n   * The consumer can call this to request an update to the underlying data.  If request has already\n   * been made or fulfilled, this is a no-op.\n   **/\n  void requestUpdate() {\n    RequestState state = kNone;\n    state_.compare_exchange_strong(state, kNeedsUpdate, std::memory_order_acq_rel);\n  }\n\n  /**\n   * The producer can check this to determine if an update is needed.\n   *\n   * @return true if an update is required, false otherwise.\n   **/\n  bool updateRequested() const {\n    return state_.load(std::memory_order_acquire) == kNeedsUpdate;\n  }\n\n  /**\n   * The producer can try to emplace a new T object in response to a request.\n   * @param args The arguments to emplace.\n   * @return true if the underlying data was updated.  false if the underlying data is not in need\n   * of an update.\n   * @note For cases where calling this superflously could be expensive, it is wise to check\n   * updateRequested() first.\n   **/\n  template <typename... Args>\n  bool tryEmplaceUpdate(Args&&... args) {\n    RequestState state = kNeedsUpdate;\n    if (!state_.compare_exchange_strong(state, kUpdating, std::memory_order_acq_rel)) {\n      return false;\n    }\n    obj_.emplace(std::forward<Args>(args)...);\n    state_.store(kReady, std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * The consumer can attempt to get an update.\n   * @return An optional wrapper to the underlying data.  If no update is ready, nullopt is\n   * returned. Once an update has been returned, the AsyncRequest object is returned to a state with\n   * no underlying data.\n   **/\n  OpResult getUpdate() {\n    if (state_.load(std::memory_order_acquire) == kReady) {\n      auto obj = std::move(obj_);\n      state_.store(kNone, std::memory_order_release);\n      return obj;\n    }\n    return {};\n  }\n\n private:\n  enum RequestState { kNone, kNeedsUpdate, kUpdating, kReady };\n  alignas(kCacheLineSize) std::atomic<RequestState> state_ = {kNone};\n  OpResult obj_;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/completion_event.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file completion_event.h\n * @ingroup group_async\n * A file providing a CompletionEvent type, which gives a way to signal to waiting threads that some\n * event has been completed.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n#include <dispenso/detail/completion_event_impl.h>\n\nnamespace dispenso {\n\n/**\n * A class which can be used for one-time notify/wait scenarios.  It is basically a way to signal to\n * any waiting threads that some event has completed.  There must be a single publisher thread\n * and zero or more waiters on arbitrary threads.  <code>reset</code> may be called to restart a\n * sequence (e.g. after <code>notify</code> occurs and all waiters have successfully exited\n * <code>wait*</code>).\n **/\nclass CompletionEvent {\n public:\n  /**\n   * Notify any waiting threads that the event has completed.  It is safe for this to be called\n   * before threads call <code>wait</code>.\n   **/\n  void notify() {\n    impl_.notify(1);\n  }\n\n  /**\n   * Wait for another thread to <code>notify</code>\n   **/\n  void wait() const {\n    impl_.wait(1);\n  }\n\n  /**\n   * Peek to see if the event has been notified in any thread\n   **/\n  bool completed() const {\n    return impl_.intrusiveStatus().load(std::memory_order_acquire);\n  }\n\n  /**\n   * Wait for another thread to <code>notify</code> or for the relative timeout to expire, whichever\n   * is first.\n   *\n   * @return true if status is \"completed\", false if timed out.\n   **/\n  template <class Rep, class Period>\n  bool waitFor(const std::chrono::duration<Rep, Period>& relTime) const {\n    return impl_.waitFor(1, relTime);\n  }\n\n  /**\n   * Wait for another thread to <code>notify</code> or for the absolute timeout to expire, whichever\n   * is first.\n   *\n   * @return true if status is \"completed\", false if timed out.\n   **/\n  template <class Clock, class Duration>\n  bool waitUntil(const std::chrono::time_point<Clock, Duration>& absTime) const {\n    return impl_.waitUntil(1, absTime);\n  }\n\n  /**\n   * Resets the event to \"not-completed\".  This should not be called while an active\n   * <code>wait*\\/notify</code> sequence is still currently in play.\n   **/\n  void reset() {\n    impl_.intrusiveStatus().store(0, std::memory_order_seq_cst);\n  }\n\n private:\n  detail::CompletionEventImpl impl_{0};\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/concurrent_object_arena.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file concurrent_object_arena.h\n * @ingroup group_containers\n * A file providing concurrent object arena container.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n#include <atomic>\n#include <cassert>\n#include <cstring>\n#include <mutex>\n#include <vector>\n\nnamespace detail {\n\ntemplate <class T>\nconstexpr T log2i(const T v) {\n  T log2 = 0, val = v;\n  while (val >>= 1)\n    ++log2;\n  return log2;\n}\n\n} // namespace detail\n\nnamespace dispenso {\n/**\n * <code>ConcurrentObjectArena</code> is an indexed sequence container that\n * allows concurrent insertion to its end. Insertion never invalidates pointers\n * or references to the rest of the elements. As opposet to std::vector, the\n * elements of a <code>ConcurrentObjectArena</code> are not stored\n * contiguously. In memory it is sequence of individually allocated fixed-size\n * arrays, with additional bookkeeping. The size of arrays is always power of\n * two (to optimize indexed access)\n * <pre>\n *  buffers  |&lt;────     bufferSize      ────&gt;|\n *    ┌─┐    ┌──────────────────────────────┐\n *    │*├───>│                              │\n *    ├─┤    ├──────────────────────────────┤\n *    │*├───>│                              │\n *    ├─┤    ├──────────────────────────────┤\n *    │*├───>│                              │\n *    └─┘    └──────────────────────────────┘\n *</pre>\n **/\ntemplate <class T, class Index = size_t, size_t alignment = dispenso::kCacheLineSize>\nstruct ConcurrentObjectArena {\n  ConcurrentObjectArena() = delete;\n  /**\n   * Construct a <code>ConcurrentObjectArena</code> with given or bigger contiguous array size\n   *\n   * @param minBuffSize The minimum size of the internal buffer. If given\n   * size is not power of 2 the closest bigger power of two would be chosen.\n   **/\n  explicit ConcurrentObjectArena(const Index minBuffSize)\n      : kLog2BuffSize(\n            ::detail::log2i(minBuffSize) +\n            ((Index{1} << ::detail::log2i(minBuffSize)) == minBuffSize ? 0 : 1)),\n        kBufferSize(Index{1} << kLog2BuffSize),\n        kMask((Index{1} << kLog2BuffSize) - 1),\n        pos_(0),\n        allocatedSize_(0),\n        buffers_(nullptr),\n        buffersSize_(0),\n        buffersPos_(0) {\n    allocateBuffer();\n    allocatedSize_.store(kBufferSize, std::memory_order_relaxed);\n  }\n\n  /**\n   * Copy constructor\n   **/\n  ConcurrentObjectArena(const ConcurrentObjectArena<T, Index, alignment>& other)\n      : kLog2BuffSize(other.kLog2BuffSize),\n        kBufferSize(other.kBufferSize),\n        kMask(other.kMask),\n        pos_(other.pos_.load(std::memory_order_relaxed)),\n        allocatedSize_(other.allocatedSize_.load(std::memory_order_relaxed)),\n        buffersSize_(other.buffersSize_),\n        buffersPos_(other.buffersPos_) {\n    T** otherBuffers = other.buffers_.load(std::memory_order_acquire);\n    T** newBuffers = new T*[buffersSize_];\n    for (Index i = 0; i < buffersSize_; ++i) {\n      void* ptr = detail::alignedMalloc(kBufferSize * sizeof(T), alignment);\n#if defined(__cpp_exceptions)\n      if (ptr == nullptr)\n        throw std::bad_alloc();\n#endif // __cpp_exceptions\n      std::memcpy(ptr, otherBuffers[i], kBufferSize * sizeof(T));\n      newBuffers[i] = static_cast<T*>(ptr);\n    }\n    buffers_.store(newBuffers, std::memory_order_release);\n  }\n\n  /**\n   * Move constructor\n   **/\n  ConcurrentObjectArena(ConcurrentObjectArena<T, Index, alignment>&& other) noexcept\n      : kLog2BuffSize(0),\n        kBufferSize(0),\n        kMask(0),\n        pos_(0),\n        allocatedSize_(0),\n        buffers_(nullptr),\n        buffersSize_(0),\n        buffersPos_(0) {\n    swap(*this, other);\n  }\n\n  ~ConcurrentObjectArena() {\n    T** buffers = buffers_.load(std::memory_order_acquire);\n\n    for (Index i = 0; i < buffersPos_; i++)\n      detail::alignedFree(buffers[i]);\n\n    delete[] buffers;\n\n    for (T** p : deleteLater_)\n      delete[] p;\n  }\n\n  /**\n   * Copy assignment operator.  This is not concurrency safe.\n   **/\n  ConcurrentObjectArena<T, Index, alignment>& operator=(\n      ConcurrentObjectArena<T, Index, alignment> const& other) {\n    ConcurrentObjectArena<T, Index, alignment> copy(other);\n    swap(*this, copy);\n    return *this;\n  }\n\n  /**\n   * Move assignment operator.  This is not concurrency safe.\n   **/\n  ConcurrentObjectArena<T, Index, alignment>& operator=(\n      ConcurrentObjectArena<T, Index, alignment>&& other) noexcept {\n    swap(*this, other);\n    return *this;\n  }\n  /**\n   * Grow a container\n   *\n   * This function is thread safe and never invalidates pointers or\n   * references to the rest of the elements. It is lock-free if new elements\n   * can be placed in current buffer. It locks if it allocates a new buffer.\n   * @param delta New size of the container will be <code>delta</code> elements bigger.\n   * @return index of the first element of the allocated group.\n   **/\n  Index grow_by(const Index delta) {\n    Index newPos;\n    Index oldPos = pos_.load(std::memory_order_relaxed);\n\n    do {\n      Index curSize = allocatedSize_.load(std::memory_order_acquire);\n\n      if (oldPos + delta >= curSize) {\n        const std::lock_guard<std::mutex> guard(resizeMutex_);\n        curSize = allocatedSize_.load(std::memory_order_relaxed);\n        while (oldPos + delta >= curSize) {\n          allocateBuffer();\n          allocatedSize_.store(curSize + kBufferSize, std::memory_order_release);\n          curSize = curSize + kBufferSize;\n        }\n      }\n\n      newPos = oldPos + delta;\n    } while (!std::atomic_compare_exchange_weak_explicit(\n        &pos_, &oldPos, newPos, std::memory_order_release, std::memory_order_relaxed));\n\n    constructObjects(oldPos, oldPos + delta);\n\n    return oldPos;\n  }\n\n  /**\n   * Access an element of the object arena.  Concurrency safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  inline const T& operator[](const Index index) const {\n    const Index bufIndex = index >> kLog2BuffSize;\n    const Index i = index & kMask;\n\n    return buffers_.load(std::memory_order_acquire)[bufIndex][i];\n  }\n\n  /**\n   * Access an element of the object arena.  Concurrency safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  inline T& operator[](const Index index) {\n    return const_cast<T&>(\n        const_cast<const ConcurrentObjectArena<T, Index, alignment>&>(*this)[index]);\n  }\n\n  /**\n   * Get the size of the object arena.  Concurrency safe.\n   * @return The number of elements in the object arena.  Note that elements can be appended\n   *concurrently with this call.\n   **/\n  Index size() const {\n    return pos_.load(std::memory_order_relaxed);\n  }\n\n  /**\n   * The current capacity of the object arena. Concurrency safe.\n   * @return The current capacity. Note that elements can be appended concurrently\n   **/\n  Index capacity() const {\n    return allocatedSize_.load(std::memory_order_relaxed);\n  }\n\n  /**\n   * Number of the internal buffers. Concurrency  safe.\n   * @return The current number of buffers. Note that buffers can be appended concurrently\n   **/\n  Index numBuffers() const {\n    return buffersPos_;\n  }\n\n  /**\n   * Get the pointer to the buffer. Concurrency safe.\n   * @param index index of the buffer\n   * @return The pointer to the buffer.\n   **/\n  const T* getBuffer(const Index index) const {\n    return buffers_.load(std::memory_order_acquire)[index];\n  }\n\n  /**\n   * Get the pointer to the buffer. Concurrency safe.\n   * @param index index of the buffer\n   * @return The pointer to the buffer.\n   **/\n  T* getBuffer(const Index index) {\n    return buffers_.load(std::memory_order_acquire)[index];\n  }\n\n  /**\n   * Get the used buffer size. not concurrency safe.\n   * @param index index of the buffer.\n   * @return The used buffer size.\n   **/\n  Index getBufferSize(const Index index) const {\n    const Index numBuffs = numBuffers();\n    assert(index < numBuffs);\n\n    if (index < numBuffs - 1)\n      return kBufferSize;\n    else\n      return pos_.load(std::memory_order_relaxed) - (kBufferSize * (numBuffs - 1));\n  }\n\n  /**\n   * Swap the contents of containers lhs, and rhs.  This is not concurrency safe.\n   * @param lhs object arena to swap\n   * @param rhs object arena to swap\n   **/\n  friend void swap(\n      ConcurrentObjectArena<T, Index, alignment>& lhs,\n      ConcurrentObjectArena<T, Index, alignment>& rhs) noexcept {\n    using std::swap;\n\n    swap(lhs.kLog2BuffSize, rhs.kLog2BuffSize);\n    swap(lhs.kBufferSize, rhs.kBufferSize);\n    swap(lhs.kMask, rhs.kMask);\n\n    const Index rhs_pos = rhs.pos_.load(std::memory_order_relaxed);\n    rhs.pos_.store(lhs.pos_.load(std::memory_order_relaxed), std::memory_order_relaxed);\n    lhs.pos_.store(rhs_pos, std::memory_order_relaxed);\n\n    const Index rhs_allocatedSize = rhs.allocatedSize_.load(std::memory_order_relaxed);\n    rhs.allocatedSize_.store(\n        lhs.allocatedSize_.load(std::memory_order_relaxed), std::memory_order_relaxed);\n    lhs.allocatedSize_.store(rhs_allocatedSize, std::memory_order_relaxed);\n\n    T** const rhs_buffers = rhs.buffers_.load(std::memory_order_acquire);\n    rhs.buffers_.store(lhs.buffers_.load(std::memory_order_acquire), std::memory_order_release);\n    lhs.buffers_.store(rhs_buffers, std::memory_order_release);\n\n    swap(lhs.buffersSize_, rhs.buffersSize_);\n    swap(lhs.buffersPos_, rhs.buffersPos_);\n    swap(lhs.deleteLater_, rhs.deleteLater_);\n  }\n\n private:\n  void allocateBuffer() {\n    void* ptr = detail::alignedMalloc(kBufferSize * sizeof(T), alignment);\n#if defined(__cpp_exceptions)\n    if (ptr == nullptr)\n      throw std::bad_alloc();\n#endif // __cpp_exceptions\n\n    if (buffersPos_ < buffersSize_) {\n      buffers_.load(std::memory_order_acquire)[buffersPos_++] = static_cast<T*>(ptr);\n    } else {\n      const Index oldBuffersSize = buffersSize_;\n      T** oldBuffers = buffers_.load(std::memory_order_acquire);\n\n      buffersSize_ = oldBuffersSize == 0 ? 2 : oldBuffersSize * 2;\n      T** newBuffers = new T*[buffersSize_];\n\n      if (oldBuffers != nullptr) {\n        std::memcpy(newBuffers, oldBuffers, sizeof(T*) * oldBuffersSize);\n        deleteLater_.push_back(oldBuffers);\n      }\n\n      newBuffers[buffersPos_++] = static_cast<T*>(ptr);\n      buffers_.store(newBuffers, std::memory_order_release);\n    }\n  }\n\n  void constructObjects(const Index beginIndex, const Index endIndex) {\n    const Index startBuffer = beginIndex >> kLog2BuffSize;\n    const Index endBuffer = endIndex >> kLog2BuffSize;\n\n    Index bufStart = beginIndex & kMask;\n    for (Index b = startBuffer; b <= endBuffer; ++b) {\n      T* buf = buffers_.load(std::memory_order_acquire)[b];\n      const Index bufEnd = b == endBuffer ? (endIndex & kMask) : kBufferSize;\n      for (Index i = bufStart; i < bufEnd; ++i)\n        new (buf + i) T();\n\n      bufStart = 0;\n    }\n  }\n  //\n  //    kBufferSize = 2^kLog2BuffSize\n  //    mask = 0b00011111\n  //                ──┬──\n  //                  └─number of 1s is log2BuffSize\n  //\n  std::mutex resizeMutex_;\n\n  Index kLog2BuffSize;\n  Index kBufferSize;\n  Index kMask;\n\n  std::atomic<Index> pos_;\n  std::atomic<Index> allocatedSize_;\n\n  std::atomic<T**> buffers_;\n  Index buffersSize_;\n  Index buffersPos_;\n  std::vector<T**> deleteLater_;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/concurrent_vector.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file concurrent_vector.h\n * @ingroup group_containers\n * A file providing a concurrent vector implementation.  The basic implementation is similar to\n * common implementation of deques, with a two-level array structure.  For ConcurrentVector, this is\n * an array of buffers that grow by powers of two.  The interface is intended to be a reasonably\n * complete standin for both std::vector and tbb::concurrent_vector.  When compared to std::vector,\n * it is missing only the .data() accessor, because it is not possible to access the contents as a\n * contiguous buffer.  The interface is also compatible with TBB's concurrent_vector, but provides\n * slightly more functionality to be compatible with std::vector (e.g. .insert() and .erase()), and\n * also to enable higher performance without requiring double-initialization in some grow_by cases\n * (via .grow_by_generator()).  ConcurrentVector also has a reserving Constructor that can allow for\n * better performance when the size (or maximum size, or even a guess at the size) is known ahead of\n * time.\n *\n * Like std::deque, and unlike std::vector, it is possible to use non-movable objects in\n * ConcurrentVector, and references are not invalidated when growing the ConcurrentVector. Iterators\n * are also stable under these conditions.  One other important difference to the std containers,\n * and also to tbb::concurrentvector is that ConcurrentVector does not take an Allocator, but just\n * uses appropriately aligned malloc/free for allocation.\n *\n * Basically speaking, it is possible to grow the ConcurrentVector concurrently (e.g. via\n * .grow_by(), .emplace_back(), etc...) very quickly, and it is safe to iterate ranges of the vector\n * that have already been inserted (and e.g. .begin(), and .end() are thread-safe).  As with TBB's\n * implementation, it is not safe to concurrently call .pop_back(), .reserve(), .resize(), etc...\n * The operation of these functions is lock-free if memory allocation is also lock-free.\n *\n * @note Synchronization model: concurrent growth operations (push_back, emplace_back, grow_by)\n * provide thread-safe index allocation, but do NOT guarantee that elements are visible to other\n * threads immediately.  Reading an element that is being concurrently constructed by another thread\n * is a data race.  Callers must establish their own happens-before relationship (e.g. via a mutex,\n * atomic flag, or task completion) between the writer finishing construction and the reader\n * accessing the element.  This is consistent with tbb::concurrent_vector's model.\n *\n * As of this writing, with the benchmarks developed for testing ConcurrentVector, ConcurrentVector\n * appears to be faster than tbb::concurrent_vector by a factor of between about 15% and 3x\n * (depending on the operation).  ConcurrentVector's iteration and random access is on-par with\n * std::deque (libstdc++), sometimes a bit faster, sometimes a bit slower, but .push_back() is about\n * an order of magnitude slower for serial use (note that by using one of the .grow_by() variants\n * could make this on-par for serial code, if applicable, see the \"alternative\" benchmarks).\n *\n * Most notably, in the parallel growth benchmarks, (on Clang 8, Linux, 32-core Threadripper\n * 2990WX), ConcurrentVector is between about 5x and 20x faster than std::vector + std::mutex, and\n * is about 1.6x faster than tbb::concurrent_vector.\n **/\n\n#pragma once\n\n#include <algorithm>\n#include <cassert>\n#include <climits>\n#include <cstring>\n#include <initializer_list>\n#include <stdexcept>\n#include <utility>\n\n#include <dispenso/detail/math.h>\n#include <dispenso/platform.h>\n#include <dispenso/tsan_annotations.h>\n\n// Whether to use a non-atomic buffer pointer cache for read-hot paths.\n// Disabled on ARM where cache-line writes on every growth operation cause store buffer\n// pressure that exceeds the read-path benefit (acquire loads are effectively free for\n// sequential access patterns on ARM).\n#if !defined(DISPENSO_HAS_CACHED_PTRS)\n#if !defined(__aarch64__) && !defined(_M_ARM64)\n#define DISPENSO_HAS_CACHED_PTRS 1\n#else\n#define DISPENSO_HAS_CACHED_PTRS 0\n#endif\n#endif\n\nnamespace dispenso {\n\n/**\n * Available strategies to use for ConcurrentVector reallocation.  kFullBufferAhead means that once\n * we begin to use a buffer, we will also ensure that the next buffer is allocated. kHalfBufferAhead\n * means that once we begin to use an address halfway through the current buffer, we will allocate\n * the next buffer.  kAsNeeded means that once we are ready to use an address in the next buffer (we\n * are using the last valid address in the current buffer), we allocate the next buffer.  kAsNeeded\n * should be the default to avoid using too much memory, but a small speedup is possible due to less\n * thread waiting when the other options are used.  kFullBufferAhead is fastest, then\n * kHalfBufferAhead, then kAsNeeded, and the correspondingly kFullBufferAhead uses the most memory,\n * then kHalfBufferAhead, and kAsNeeded uses the least.\n **/\nenum class ConcurrentVectorReallocStrategy { kFullBufferAhead, kHalfBufferAhead, kAsNeeded };\n\nstruct ReserveTagS {};\n/**\n * This ReserveTag can be passed into the reserving constructor for better performance, if even a\n * rough guess can be made at the number of elements that will be required.\n **/\nconstexpr ReserveTagS ReserveTag;\n\n// Textual inclusion.  Includes undocumented implementation details, e.g. iterators.\n#include <dispenso/detail/concurrent_vector_impl.h>\n\n/**\n * The default ConcurrentVector traits type for defining capacities and max capacities.  Both\n * members are required should one wish to supply a custom set of traits.\n **/\ntemplate <typename T>\nstruct DefaultConcurrentVectorSizeTraits {\n  /**\n   * @brief This is the starting user-expected capacity in number of elements (algorithm may provide\n   * more based on kReallocStrategy)\n   **/\n  static constexpr size_t kDefaultCapacity = (sizeof(T) >= 256) ? 2 : 512 / sizeof(T);\n\n  /**\n   * @brief The maximum possible size for the vector.\n   *\n   * The reason this exists is because if someone doesn't require vectors of length in e.g.\n   * petabytes, the class can use less space.  Additionally, some minor optimizations may be\n   * possible if the max size is less than 32-bits.\n   **/\n  static constexpr size_t kMaxVectorSize =\n      (size_t{1} << (sizeof(size_t) * CHAR_BIT > 47 ? 47 : sizeof(size_t) * CHAR_BIT - 1)) /\n      sizeof(T);\n};\n\n/**\n * The default ConcurrentVector traits type.  All members are required should one wish to supply a\n * custom set of traits.\n **/\nstruct DefaultConcurrentVectorTraits {\n  /**\n   * @brief Prefer to place the pointers to the buffers inline in the class.\n   *\n   * This can consume a lot of space, e.g. on the stack.  This can be a couple of kilobytes.  But\n   * performance is improved by 5% to 15%.  When set to false, this results in those pointers\n   * residing in a separate heap allocation.\n   **/\n  static constexpr bool kPreferBuffersInline = true;\n\n  /**\n   * @brief How far/whether to allocate before memory is required.\n   *\n   * We can allocate ahead, which may reduce the chances of another thread blocking while waiting\n   * for memory to be allocated.  This implies a pretty stiff memory overhead, which people may not\n   * want to pay (up to 3x overhead after the first bucket for kFullBufferAhead).  This can be set\n   * to kAsNeeded instead of kFullBufferAhead, which makes overheads similar to typical std::vector\n   * implementation (up to 2x overhead).  Performance differences are modest, so unless you need to\n   * squeeze the most out of your use, kAsNeeded is okay.\n   **/\n  static constexpr ConcurrentVectorReallocStrategy kReallocStrategy =\n      ConcurrentVectorReallocStrategy::kAsNeeded;\n\n  /**\n   * @brief Should we prefer faster, but larger iterators, or slower, but smaller iterators.\n   *\n   * If an algorithm needs to store iterators for later use, size overhead could become a\n   * concern.  By using kIteratorPreferSpeed == true, the size of an iterator will be roughly double\n   * the iterator when kIteratorPreferSpeed == false.  Conversely, iterate + dereference is also\n   * about twice as fast.\n   *\n   **/\n  static constexpr bool kIteratorPreferSpeed = true;\n};\n\n/**\n * A concurrent vector type.  It is safe to call .push_back(), .emplace_back(), the various .grow_()\n * functions, .begin(), .end(), .size(), .empty() concurrently, and existing iterators and\n *references remain valid with these functions' use.\n **/\ntemplate <\n    typename T,\n    typename Traits = DefaultConcurrentVectorTraits,\n    typename SizeTraits = DefaultConcurrentVectorSizeTraits<T>>\nclass ConcurrentVector {\n public:\n  using value_type = T;\n  using reference = T&;\n  using const_reference = const T&;\n  using size_type = size_t;\n  using difference_type = ssize_t;\n  using reference_type = T&;\n  using const_reference_type = const T&;\n  using pointer = T*;\n  using const_pointer = const T*;\n  using iterator = std::conditional_t<\n      Traits::kIteratorPreferSpeed,\n      cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T, false>,\n      cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T, false>>;\n  using const_iterator = std::conditional_t<\n      Traits::kIteratorPreferSpeed,\n      cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T, true>,\n      cv::CompactCVecIterator<ConcurrentVector<T, Traits>, T, true>>;\n  using reverse_iterator = std::reverse_iterator<iterator>;\n  using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n\n  /**\n   * Default construct the ConcurrentVector.\n   **/\n  ConcurrentVector() : ConcurrentVector(SizeTraits::kDefaultCapacity / 2, ReserveTag) {}\n\n  /**\n   * The reserving constructor.  By supplying a reasonable starting capacity, e.g. close to max\n   * expected vector size, this can often improve performance substantially by reducing allocations\n   * and increasing data coherency.\n   **/\n  ConcurrentVector(size_t startCapacity, ReserveTagS)\n      : firstBucketShift_(\n            detail::log2(\n                detail::nextPow2(std::max(startCapacity, SizeTraits::kDefaultCapacity / 2)))),\n        firstBucketLen_(size_type{1} << firstBucketShift_) {\n    T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);\n    initCachedPtrs();\n    setCachedPtr(0, firstTwo);\n    setCachedPtr(1, firstTwo + firstBucketLen_);\n    buffers_[0].store(firstTwo, std::memory_order_release);\n    buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_release);\n  }\n\n  /**\n   * Sizing constructor with default initialization.\n   **/\n  explicit ConcurrentVector(size_t startSize) : ConcurrentVector(startSize, ReserveTag) {\n    size_.store(startSize, std::memory_order_relaxed);\n    T* buf = buffers_[0].load(std::memory_order_relaxed);\n    for (size_t i = 0; i < startSize; ++i) {\n      new (buf + i) T();\n    }\n  }\n\n  /**\n   * Sizing constructor with specified default value.\n   **/\n  ConcurrentVector(size_t startSize, const T& defaultValue)\n      : ConcurrentVector(startSize, ReserveTag) {\n    size_.store(startSize, std::memory_order_relaxed);\n    T* buf = buffers_[0].load(std::memory_order_relaxed);\n    for (size_t i = 0; i < startSize; ++i) {\n      new (buf + i) T(defaultValue);\n    }\n  }\n\n  /**\n   * Constructor taking an iterator range.\n   **/\n  template <typename InIterator>\n  ConcurrentVector(InIterator start, InIterator end)\n      : ConcurrentVector(std::distance(start, end), start, end) {}\n\n  /**\n   * Sizing constructor taking an iterator range.  If size is known in advance, this may be faster\n   * than just providing the iterator range, especially for input iterators that are not random\n   * access.\n   **/\n  template <typename InIterator>\n  ConcurrentVector(size_type startSize, InIterator start, InIterator end)\n      : ConcurrentVector(startSize, ReserveTag) {\n    size_.store(startSize, std::memory_order_relaxed);\n    assert(std::distance(start, end) == static_cast<difference_type>(startSize));\n    internalInit(start, end, begin());\n  }\n\n  /**\n   * Construct via initializer list\n   **/\n  ConcurrentVector(std::initializer_list<T> l)\n      : ConcurrentVector(l.size(), std::begin(l), std::end(l)) {}\n\n  /**\n   * Copy constructor\n   **/\n  ConcurrentVector(const ConcurrentVector& other)\n      : ConcurrentVector(other.size(), other.cbegin(), other.cend()) {}\n\n  /**\n   * Move constructor\n   **/\n  ConcurrentVector(ConcurrentVector&& other)\n      : buffers_(std::move(other.buffers_)),\n        firstBucketShift_(other.firstBucketShift_),\n        firstBucketLen_(other.firstBucketLen_),\n        size_(other.size_.load(std::memory_order_relaxed)) {\n    moveCachedPtrsFrom(other);\n    other.size_.store(0, std::memory_order_relaxed);\n    // This is possibly unnecessary overhead, but enables the \"other\" vector to be in a valid,\n    // usable state right away, no empty check or clear required, as it is for std::vector.\n    T* firstTwo = cv::alloc<T>(2 * firstBucketLen_);\n    other.setCachedPtr(0, firstTwo);\n    other.setCachedPtr(1, firstTwo + firstBucketLen_);\n    other.buffers_[0].store(firstTwo, std::memory_order_relaxed);\n    other.buffers_[1].store(firstTwo + firstBucketLen_, std::memory_order_relaxed);\n  }\n\n  /**\n   * Copy assignment operator.  This is not concurrency safe.\n   **/\n  ConcurrentVector& operator=(const ConcurrentVector& other) {\n    if (&other == this) {\n      return *this;\n    }\n\n    clear();\n    reserve(other.size());\n    size_.store(other.size(), std::memory_order_relaxed);\n    internalInit(other.cbegin(), other.cend(), begin());\n\n    return *this;\n  }\n\n  /**\n   * Move assignment operator.  This is not concurrency safe.\n   **/\n  ConcurrentVector& operator=(ConcurrentVector&& other) {\n    using std::swap;\n    if (&other == this) {\n      return *this;\n    }\n\n    clear();\n    swap(firstBucketShift_, other.firstBucketShift_);\n    swap(firstBucketLen_, other.firstBucketLen_);\n    buffers_ = std::move(other.buffers_);\n    swapCachedPtrs(other);\n    size_t curLen = size_.load(std::memory_order_relaxed);\n    size_.store(other.size_.load(std::memory_order_relaxed), std::memory_order_relaxed);\n    other.size_.store(curLen, std::memory_order_relaxed);\n\n    return *this;\n  }\n\n  /**\n   * Assign the vector.  Not concurrency safe.\n   *\n   * @param count The number of elements to have in the vector\n   * @param value The value to copy into each element\n   **/\n  void assign(size_type count, const T& value) {\n    clear();\n    reserve(count);\n    size_.store(count, std::memory_order_relaxed);\n    internalFillN(begin(), count, value);\n  }\n\n  /**\n   * Assign the vector.  Not concurrency safe.\n   *\n   * @param start The beginning of the iterator range to assign into the vector\n   * @param end The end of the iterator range to assign into the vector\n   **/\n  template <\n      typename It,\n      typename = typename std::iterator_traits<It>::difference_type,\n      typename = typename std::iterator_traits<It>::pointer,\n      typename = typename std::iterator_traits<It>::reference,\n      typename = typename std::iterator_traits<It>::value_type,\n      typename = typename std::iterator_traits<It>::iterator_category>\n  void assign(It start, It end) {\n    clear();\n    auto count = std::distance(start, end);\n    reserve(count);\n    size_.store(count, std::memory_order_relaxed);\n    internalInit(start, end, begin());\n  }\n\n  /**\n   * Reserve some capacity for the vector.  Not concurrency safe.\n   *\n   * @param capacity The amount of space to ensure is available to avoid further allocations.\n   **/\n  void reserve(difference_type capacity) {\n    auto bend = bucketAndSubIndex(capacity);\n    allocateBufferRange({0, 0, firstBucketLen_}, capacity, bend);\n  }\n\n  /**\n   * Resize the vector, using default initialization for any new values.  Not concurrency safe.\n   *\n   * @param len The length of the vector after the resize.\n   **/\n  void resize(difference_type len) {\n    difference_type curLen = static_cast<difference_type>(size_.load(std::memory_order_relaxed));\n    if (curLen < len) {\n      grow_to_at_least(len);\n    } else if (curLen > len) {\n      auto it = end();\n      auto newEnd = begin() + len;\n      do {\n        --it;\n        it->~T();\n      } while (it != newEnd);\n      size_.store(len, std::memory_order_relaxed);\n    }\n  }\n\n  /**\n   * Resize the vector, copying the provided value into any new elements.  Not concurrency safe.\n   *\n   * @param len The length of the vector after the resize.\n   * @param value The value to copy into any new elements.\n   **/\n  void resize(difference_type len, const T& value) {\n    difference_type curLen = static_cast<difference_type>(size_.load(std::memory_order_relaxed));\n    if (curLen < len) {\n      grow_to_at_least(len, value);\n    } else if (curLen > len) {\n      auto it = end();\n      auto newEnd = begin() + len;\n      do {\n        --it;\n        it->~T();\n      } while (it != newEnd);\n      size_.store(len, std::memory_order_relaxed);\n    }\n  }\n\n  /**\n   * The default capacity of this vector.\n   * @return The capacity if the vector were cleared and then called shrink_to_fit.\n   **/\n  size_type default_capacity() const {\n    return 2 * firstBucketLen_;\n  }\n\n  /**\n   * The current capacity of the vector.  Not concurrency safe.\n   * @return The current capacity.\n   **/\n  size_type capacity() const {\n    size_t cap = 2 * firstBucketLen_;\n    for (size_t b = 2; b < kMaxBuffers; ++b) {\n      if (!buffers_[b].load(std::memory_order_relaxed)) {\n        break;\n      }\n      cap *= 2;\n    }\n    return cap;\n  }\n\n  /**\n   * Clear the vector.  This does not deallocate buffers, but just ensures that all elements are\n   * destructed.  Size will be zero after the call.  Not concurrency safe.\n   **/\n  void clear() {\n    auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));\n    size_t len = binfo.bucketIndex;\n    size_t cap = binfo.bucketCapacity;\n    size_t b = binfo.bucket;\n    do {\n      T* buf = buffers_[b].load(std::memory_order_relaxed);\n      T* t = buf + len;\n\n      while (t != buf) {\n        --t;\n        t->~T();\n      }\n      cap >>= int{b > 1};\n      len = cap;\n    } while (b--);\n    size_.store(0, std::memory_order_release);\n  }\n\n  /**\n   * Gets rid of extra capacity that is not needed to maintain preconditions.  At least the default\n   * capacity will remain, even if the size of the vector is zero.  Not concurrency safe.\n   **/\n  void shrink_to_fit() {\n    constexpr size_t kMaxExtra = 2;\n    auto binfo = bucketAndSubIndex(size_.load(std::memory_order_relaxed));\n\n    // We need to at least skip the first two buckets, since we have those as a single allocation.\n    size_t startBucket = std::max<size_t>(2, binfo.bucket + kMaxExtra);\n\n    for (size_t b = startBucket; b < kMaxBuffers; ++b) {\n      T* ptr = buffers_[b].load(std::memory_order_relaxed);\n      if (!ptr) {\n        break;\n      }\n      if (buffers_.shouldDealloc(b)) {\n        cv::dealloc<T>(ptr);\n      }\n      clearCachedPtr(b);\n      buffers_[b].store(nullptr, std::memory_order_release);\n    }\n  }\n\n  /**\n   * Destruct the vector.\n   **/\n  ~ConcurrentVector() {\n    clear();\n    shrink_to_fit();\n    cv::dealloc<T>(buffers_[0].load(std::memory_order_acquire));\n  }\n\n  /**\n   * Insert a value. Not concurrency safe.\n   * @param pos The point of insertion.\n   * @param value The value to copy into the element at pos.\n   * @return The iterator at the inserted position.\n   **/\n  iterator insert(const_iterator pos, const T& value) {\n    auto it = insertPartial(pos);\n    new (&*it) T(value);\n    return it;\n  }\n\n  /**\n   * Insert a value.  Not concurrency safe.\n   * @param pos The point of insertion.\n   * @param value The value to move into the element at pos.\n   * @return The iterator at the inserted position.\n   **/\n  iterator insert(const_iterator pos, T&& value) {\n    auto it = insertPartial(pos);\n    new (&*it) T(std::move(value));\n    return it;\n  }\n\n  /**\n   * Insert a value. Not concurrency safe.\n   * @param pos The point of insertion.\n   * @param count The number of elements to insert.\n   * @param value The value to copy into each inserted element starting at pos.\n   * @return The iterator at the inserted position.\n   **/\n  iterator insert(const_iterator pos, size_type count, const T& value) {\n    auto it = insertPartial(pos, count);\n    std::fill_n(it, count, value);\n    return it;\n  }\n\n  /**\n   * Insert a range of values. Not concurrency safe.\n   * @param pos The point of insertion.\n   * @param first The start of the input iterator range.\n   * @param last The end of the input iterator range.\n   * @return The iterator at the inserted position.\n   **/\n  template <\n      typename InputIt,\n      typename = typename std::iterator_traits<InputIt>::difference_type,\n      typename = typename std::iterator_traits<InputIt>::pointer,\n      typename = typename std::iterator_traits<InputIt>::reference,\n      typename = typename std::iterator_traits<InputIt>::value_type,\n      typename = typename std::iterator_traits<InputIt>::iterator_category>\n  iterator insert(const_iterator pos, InputIt first, InputIt last) {\n    size_t len = std::distance(first, last);\n    auto it = insertPartial(pos, len);\n    std::copy_n(first, len, it);\n    return it;\n  }\n\n  /**\n   * Insert an initializer_list. Not concurrency safe.\n   * @param pos The point of insertion.\n   * @param ilist The initializer_list.\n   * @return The iterator at the inserted position.\n   **/\n  iterator insert(const_iterator pos, std::initializer_list<T> ilist) {\n    return insert(pos, ilist.begin(), ilist.end());\n  }\n\n  /**\n   * Erase one element.  Not concurrency safe.\n   * @param pos The point of erasure.\n   * @return Iterator following the removed element. If pos refers to the last element, then\n   * the end() iterator is returned.\n   **/\n  iterator erase(const_iterator pos) {\n    auto e = end();\n    if (e == pos) {\n      return e;\n    }\n    size_.fetch_sub(1, std::memory_order_relaxed);\n    --e;\n    if (e == pos) {\n      e->~T();\n      return e;\n    }\n    ++e;\n    auto it = begin();\n    it += (pos - it);\n    return std::move(pos + 1, const_iterator(e), it);\n  }\n\n  /**\n   * Erase a range of elements.  Not concurrency safe.\n   * @param first The starting point of erasure.\n   * @param last The ending point of erasure.\n   * @return Iterator following the last removed element. If pos refers to the last element, then\n   * the end() iterator is returned. If last==end() prior to removal, then the updated end()\n   * iterator is returned. If [first, last) is an empty range, then last is returned.\n   **/\n  iterator erase(const_iterator first, const_iterator last) {\n    size_t len = std::distance(first, last);\n    auto it = begin();\n    size_t startIdx = first - it;\n    if (len == 0) {\n      return it + (startIdx + len);\n    }\n    it += startIdx;\n\n    auto e_it = std::move(last, cend(), it);\n\n    if (e_it < last) {\n      // remove any values that were not already moved into\n      do {\n        --last;\n        last->~T();\n      } while (e_it != last);\n    }\n    size_.fetch_sub(len, std::memory_order_relaxed);\n    return e_it;\n  }\n\n  /**\n   * Push a value onto the end of the vector.  Concurrency safe.\n   * @param val The value to copy into the new element.\n   * @return The iterator at the point of insertion.\n   **/\n  iterator push_back(const T& val) {\n    return emplace_back(val);\n  }\n\n  /**\n   * Push a value onto the end of the vector.  Concurrency safe.\n   * @param val The value to move into the new element.\n   * @return The iterator at the point of insertion.\n   **/\n  iterator push_back(T&& val) {\n    return emplace_back(std::move(val));\n  }\n\n  /**\n   * Push a value onto the end of the vector.  Concurrency safe.\n   * @param args The arg pack used to construct the new element.\n   * @return The iterator at the point of insertion.\n   **/\n  template <typename... Args>\n  iterator emplace_back(Args&&... args) {\n    auto index = size_.fetch_add(1, std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(index);\n\n    allocateBuffer(binfo);\n\n    iterator ret{this, index, binfo};\n\n    if (Traits::kIteratorPreferSpeed) {\n      new (&*ret) T(std::forward<Args>(args)...);\n    } else {\n      new (buffers_[binfo.bucket] + binfo.bucketIndex) T(std::forward<Args>(args)...);\n    }\n\n    return ret;\n  }\n\n  /**\n   * Grow the vector, constructing new elements via a generator.  Concurrency safe.\n   * @param delta The number of elements to grow by.\n   * @param gen The generator to use to construct new elements.  Must have operator()() and return a\n   * valid T.\n   * @return The iterator to the start of the grown range.\n   **/\n  template <typename Gen>\n  iterator grow_by_generator(size_type delta, Gen gen) {\n    iterator ret = growByUninitialized(delta);\n    for (auto it = ret; delta--; ++it) {\n      new (&*it) T(gen());\n    }\n    return ret;\n  }\n\n  /**\n   * Grow the vector, copying the provided value into new elements.  Concurrency safe.\n   * @param delta The number of elements to grow by.\n   * @param t The value to copy into all new elements.\n   * @return The iterator to the start of the grown range.\n   **/\n  iterator grow_by(size_type delta, const T& t) {\n    iterator ret = growByUninitialized(delta);\n    internalFillN(ret, delta, t);\n    return ret;\n  }\n\n  /**\n   * Grow the vector, default initializing new elements.  Concurrency safe.\n   * @param delta The number of elements to grow by.\n   * @return The iterator to the start of the grown range.\n   **/\n  iterator grow_by(size_type delta) {\n    iterator ret = growByUninitialized(delta);\n    internalFillDefaultN(ret, delta);\n    return ret;\n  }\n\n  /**\n   * Grow the vector with an input iterator range.  Concurrency safe.\n   * @param start The start of the input iterator range.\n   * @param end The end of the input iterator range.\n   * @return The iterator to the start of the grown range.\n   **/\n  template <\n      typename It,\n      typename = typename std::iterator_traits<It>::difference_type,\n      typename = typename std::iterator_traits<It>::pointer,\n      typename = typename std::iterator_traits<It>::reference,\n      typename = typename std::iterator_traits<It>::value_type,\n      typename = typename std::iterator_traits<It>::iterator_category>\n  iterator grow_by(It start, It end) {\n    iterator ret = growByUninitialized(std::distance(start, end));\n    internalInit(start, end, ret);\n    return ret;\n  }\n\n  /**\n   * Grow the vector with an initializer_list.  Concurrency safe.\n   * @param initList The initializer_list to use to initialize the newly added range.\n   * @return The iterator to the start of the grown range.\n   **/\n  iterator grow_by(std::initializer_list<T> initList) {\n    return grow_by(std::begin(initList), std::end(initList));\n  }\n\n  /**\n   * Grow the vector to at least the desired size, default initializing new elements.  Concurrency\n   * safe.\n   * @param n The required length\n   * @return The iterator to the nth element.\n   **/\n  iterator grow_to_at_least(size_type n) {\n    size_t curSize = size_.load(std::memory_order_relaxed);\n    if (curSize < n) {\n      return grow_by(n - curSize);\n    }\n    return {this, n - 1, bucketAndSubIndex(n - 1)};\n  }\n\n  /**\n   * Grow the vector to at least the desired size, copying the provided value into new elements.\n   * Concurrency safe.\n   * @param n The required length\n   * @param t The value to copy into each new element.\n   * @return The iterator to the nth element.\n   **/\n  iterator grow_to_at_least(size_type n, const T& t) {\n    size_t curSize = size_.load(std::memory_order_relaxed);\n    if (curSize < n) {\n      return grow_by(n - curSize, t);\n    }\n    return {this, n - 1, bucketAndSubIndex(n - 1)};\n  }\n\n  /**\n   * Pop the last element off the vector.  Not concurrency safe.\n   **/\n  void pop_back() {\n    auto binfo = bucketAndSubIndex(size_.fetch_sub(1, std::memory_order_relaxed) - 1);\n    T* elt = buffers_[binfo.bucket].load(std::memory_order_relaxed) + binfo.bucketIndex;\n    elt->~T();\n  }\n\n  /**\n   * Access an element of the vector.  Concurrency safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const T& operator[](size_type index) const {\n    auto binfo = bucketAndSubIndexForIndex(index);\n    T* buf = cachedBuffer(binfo.bucket);\n    return buf[binfo.bucketIndex];\n  }\n\n  /**\n   * Access an element of the vector.  Concurrency safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  T& operator[](size_type index) {\n    auto binfo = bucketAndSubIndexForIndex(index);\n    T* buf = cachedBuffer(binfo.bucket);\n    return buf[binfo.bucketIndex];\n  }\n\n  /**\n   * Access an element of the vector.  Out-of-boundes accesses generate an exception.  Concurrency\n   * safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const T& at(size_type index) const {\n#if defined(__cpp_exceptions)\n    if (index >= size_.load(std::memory_order_relaxed)) {\n      throw std::out_of_range(\"Index too large\");\n    }\n#endif\n    return operator[](index);\n  }\n\n  /**\n   * Access an element of the vector.  Out-of-boundes accesses generate an exception.  Concurrency\n   * safe.\n   * @param index The index of the element to access.\n   * @return A reference to the element at index.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  T& at(size_type index) {\n#if defined(__cpp_exceptions)\n    if (index >= size_.load(std::memory_order_relaxed)) {\n      throw std::out_of_range(\"Index too large\");\n    }\n#endif\n    return operator[](index);\n  }\n\n  /**\n   * Get an iterator to the start of the vector.  Concurrency safe.\n   * @return An iterator to the start of the vector.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  iterator begin() {\n    return {this, 0, {0, 0, firstBucketLen_}};\n  }\n\n  /**\n   * Get an iterator to the end of the vector.  Concurrency safe.\n   * @return An iterator to the end of the vector.  Note that it is possible for the end to change\n   * concurrently with this call.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  iterator end() {\n    size_t curSize = size_.load(std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(curSize);\n    return {this, curSize, binfo};\n  }\n\n  /**\n   * Get an iterator to the start of the vector.  Concurrency safe.\n   * @return An iterator to the start of the vector.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_iterator begin() const {\n    return {this, 0, {0, 0, firstBucketLen_}};\n  }\n\n  /**\n   * Get an iterator to the end of the vector.  Concurrency safe.\n   * @return An iterator to the end of the vector.  Note that it is possible for the end to change\n   * concurrently with this call.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_iterator end() const {\n    size_t curSize = size_.load(std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(curSize);\n    return {this, curSize, binfo};\n  }\n\n  /**\n   * Get an iterator to the start of the vector.  Concurrency safe.\n   * @return An iterator to the start of the vector.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_iterator cbegin() const {\n    return {this, 0, {0, 0, firstBucketLen_}};\n  }\n\n  /**\n   * Get an iterator to the end of the vector.  Concurrency safe.\n   * @return An iterator to the end of the vector.  Note that it is possible for the end to change\n   * concurrently with this call.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_iterator cend() const {\n    size_t curSize = size_.load(std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(curSize);\n    return {this, curSize, binfo};\n  }\n\n  /**\n   * Get a starting reverse iterator to the vector.  Concurrency safe.\n   * @return A starting reverse iterator to the vector. Note that it is possible for the the rbegin\n   * to change concurrently with this call.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  reverse_iterator rbegin() {\n    return reverse_iterator(end());\n  }\n\n  /**\n   * Get an ending reverse iterator to the vector.  Concurrency safe.\n   * @return An ending reverse iterator to the vector.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  reverse_iterator rend() {\n    return reverse_iterator(begin());\n  }\n\n  /**\n   * Get a starting reverse iterator to the vector.  Concurrency safe.\n   * @return A starting reverse iterator to the vector. Note that it is possible for the the rbegin\n   * to change concurrently with this call.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_reverse_iterator rbegin() const {\n    return const_reverse_iterator(cend());\n  }\n\n  /**\n   * Get an ending reverse iterator to the vector.  Concurrency safe.\n   * @return An ending reverse iterator to the vector.\n   *\n   * @note Iterators and references are stable even if other threads are inserting, but it is\n   * still the users responsibility to avoid racing on the element itself.\n   **/\n  const_reverse_iterator rend() const {\n    return const_reverse_iterator(cbegin());\n  }\n\n  /**\n   * Checks if the vector contains any elements. Concurrency safe.\n   * @return true if the vector contains no elements, false otherwise.  Note that an element could\n   * be appended concurrently with this call.\n   **/\n  bool empty() const {\n    return size_.load(std::memory_order_relaxed) == 0;\n  }\n\n  /**\n   * Get the maximum size a vector of this type can theoretically have.  Concurrency safe\n   * (constexpr).\n   * @return The max size a vector of this type could theoretically have.\n   **/\n  constexpr size_type max_size() const noexcept {\n    return Traits::kMaxVectorSize;\n  }\n\n  /**\n   * Get the size of the vector.  Concurrency safe.\n   * @return The number of elements in the vector.  Note that elements can be appended concurrently\n   * with this call.\n   **/\n  size_type size() const {\n    return size_.load(std::memory_order_relaxed);\n  }\n\n  /**\n   * Get the front element of the vector.  Concurrency safe.\n   * @return A reference to the first element in the vector.\n   **/\n  T& front() {\n    return *buffers_[0].load(std::memory_order_relaxed);\n  }\n\n  /**\n   * Get the front element of the vector.  Concurrency safe.\n   * @return A reference to the first element in the vector.\n   **/\n  const T& front() const {\n    return *buffers_[0].load(std::memory_order_relaxed);\n  }\n\n  /**\n   * Get the last element of the vector.  Concurrency safe.\n   * @return A reference to the last element in the vector.  Note that elements could be appended\n   * concurrently with this call (in which case it won't be the back anymore).\n   **/\n  T& back() {\n    return *(end() - 1);\n  }\n\n  /**\n   * Get the last element of the vector.  Concurrency safe.\n   * @return A reference to the last element in the vector.  Note that elements could be appended\n   * concurrently with this call (in which case it won't be the back anymore).\n   **/\n  const T& back() const {\n    return *(end() - 1);\n  }\n\n  /**\n   * Swap the contents (and iterators, and element references) of the current vector with oth.\n   * @param oth The vector to swap with.\n   **/\n  void swap(ConcurrentVector& oth) {\n    using std::swap;\n    swap(firstBucketShift_, oth.firstBucketShift_);\n    swap(firstBucketLen_, oth.firstBucketLen_);\n    size_t othlen = oth.size_.load(std::memory_order_relaxed);\n    oth.size_.store(size_.load(std::memory_order_relaxed), std::memory_order_relaxed);\n    size_.store(othlen, std::memory_order_relaxed);\n\n    // okay, this relies on the fact that we're essentially swapping in the move operator.\n    buffers_ = std::move(oth.buffers_);\n    swapCachedPtrs(oth);\n  }\n\n private:\n  DISPENSO_INLINE cv::BucketInfo bucketAndSubIndexForIndex(size_t index) const {\n#if defined(_MSC_VER) || defined(__aarch64__) || defined(_M_ARM64)\n    // Branching fast path — benefits MSVC and ARM where branch prediction handles\n    // sequential access patterns well, avoiding log2/division for the common case.\n    if (index < firstBucketLen_) {\n      return {0, index, firstBucketLen_};\n    }\n\n    size_t l2idx = detail::log2(index);\n    size_t bucket = (l2idx + 1) - firstBucketShift_;\n    size_t bucketCapacity = size_t{1} << l2idx;\n    size_t bucketIndex = index - bucketCapacity;\n\n    return {bucket, bucketIndex, bucketCapacity};\n#else\n    return bucketAndSubIndex(index);\n#endif // _MSC_VER || __aarch64__ || _M_ARM64\n  }\n\n  DISPENSO_INLINE cv::BucketInfo bucketAndSubIndex(size_t index) const {\n    size_t l2idx = detail::log2(index | 1);\n    size_t bucket = (l2idx + 1) - firstBucketShift_;\n    size_t bucketCapacity = size_t{1} << l2idx;\n    size_t bucketIndex = index - bucketCapacity;\n\n    bucket = index < firstBucketLen_ ? 0 : bucket;\n    bucketIndex = index < firstBucketLen_ ? index : bucketIndex;\n    bucketCapacity = index < firstBucketLen_ ? firstBucketLen_ : bucketCapacity;\n\n    return {bucket, bucketIndex, bucketCapacity};\n  }\n\n  template <typename InIterator>\n  void internalInit(InIterator start, InIterator end, iterator it) {\n    while (start != end) {\n      new (&*it) T(*start);\n      ++it;\n      ++start;\n    }\n  }\n\n  void internalFillN(iterator it, size_t len, const T& value) {\n    for (; len--; ++it) {\n      new (&*it) T(value);\n    }\n  }\n\n  void internalFillDefaultN(iterator it, size_t len) {\n    for (; len--; ++it) {\n      new (&*it) T();\n    }\n  }\n\n  iterator growByUninitialized(size_type delta) {\n    auto index = size_.fetch_add(delta, std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(index);\n    auto bend = bucketAndSubIndex(index + delta);\n    allocateBufferRange(binfo, delta, bend);\n    return {this, index, binfo};\n  }\n\n  iterator insertPartial(const_iterator pos) {\n    auto e = end();\n    auto index = size_.fetch_add(1, std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(index);\n    allocateBuffer(binfo);\n    new (&*e) T();\n    return std::move_backward(pos, const_iterator(e), e + 1) - 1;\n  }\n\n  iterator insertPartial(const_iterator pos, size_t len) {\n    auto e = end();\n    auto index = size_.fetch_add(len, std::memory_order_relaxed);\n    auto binfo = bucketAndSubIndex(index);\n    auto bend = bucketAndSubIndex(index + len);\n    allocateBufferRange(binfo, len, bend);\n    for (auto it = e + len; it != e;) {\n      --it;\n      new (&*it) T();\n    }\n    return std::move_backward(pos, const_iterator(e), e + len) - len;\n  }\n\n  alignas(kCacheLineSize) cv::ConVecBuffer<\n      T,\n      SizeTraits::kDefaultCapacity / 2,\n      SizeTraits::kMaxVectorSize,\n      Traits::kPreferBuffersInline,\n      Traits::kReallocStrategy> buffers_;\n\n  static constexpr size_t kMaxBuffers =\n      detail::log2const(SizeTraits::kMaxVectorSize / (SizeTraits::kDefaultCapacity / 2)) + 1;\n\n#if DISPENSO_HAS_CACHED_PTRS\n  // Non-atomic cache of buffer pointers for read-hot paths. Buffer pointers are write-once\n  // (never change after allocation) and are stored here BEFORE the release store to buffers_[],\n  // so any thread that acquires from buffers_[] is guaranteed to see the cached value.\n  // All concurrent writes to a given slot store the same value.\n  // Disabled on ARM where cache-line invalidation pressure exceeds the read-path benefit.\n  alignas(kCacheLineSize) mutable T* cachedPtrs_[kMaxBuffers];\n#endif\n\n  size_t firstBucketShift_;\n  size_t firstBucketLen_;\n\n  alignas(kCacheLineSize) std::atomic<size_t> size_{0};\n\n  DISPENSO_INLINE T* cachedBuffer(size_t bucket) const {\n#if DISPENSO_HAS_CACHED_PTRS\n    return cachedPtrs_[bucket];\n#else\n    // Relaxed is sufficient: callers only access indices that have been fully constructed, which\n    // requires an external happens-before with the writing thread. That synchronization\n    // transitively carries the buffer pointer visibility (which was release-stored during\n    // allocation). This matches the original pre-cache memory ordering and avoids the cost of\n    // ldar (load-acquire) on AArch64.\n    return buffers_[bucket].load(std::memory_order_relaxed);\n#endif\n  }\n\n  DISPENSO_INLINE void allocateBuffer(const cv::BucketInfo& binfo) {\n#if DISPENSO_HAS_CACHED_PTRS\n    buffers_.allocAsNecessary(binfo, cachedPtrs_);\n#else\n    buffers_.allocAsNecessary(binfo);\n#endif\n  }\n\n  DISPENSO_INLINE void\n  allocateBufferRange(const cv::BucketInfo& binfo, ssize_t rangeLen, const cv::BucketInfo& bend) {\n#if DISPENSO_HAS_CACHED_PTRS\n    buffers_.allocAsNecessary(binfo, rangeLen, bend, cachedPtrs_);\n#else\n    buffers_.allocAsNecessary(binfo, rangeLen, bend);\n#endif\n  }\n\n  DISPENSO_INLINE void initCachedPtrs() {\n#if DISPENSO_HAS_CACHED_PTRS\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      cachedPtrs_[i] = nullptr;\n    }\n#endif\n  }\n\n  DISPENSO_INLINE void setCachedPtr(size_t bucket, T* ptr) {\n#if DISPENSO_HAS_CACHED_PTRS\n    cachedPtrs_[bucket] = ptr;\n#else\n    (void)bucket;\n    (void)ptr;\n#endif\n  }\n\n  DISPENSO_INLINE void clearCachedPtr(size_t bucket) {\n#if DISPENSO_HAS_CACHED_PTRS\n    cachedPtrs_[bucket] = nullptr;\n#else\n    (void)bucket;\n#endif\n  }\n\n  DISPENSO_INLINE void moveCachedPtrsFrom(ConcurrentVector& other) {\n#if DISPENSO_HAS_CACHED_PTRS\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      cachedPtrs_[i] = other.cachedPtrs_[i];\n      other.cachedPtrs_[i] = nullptr;\n    }\n#else\n    (void)other;\n#endif\n  }\n\n  DISPENSO_INLINE void swapCachedPtrs(ConcurrentVector& other) {\n#if DISPENSO_HAS_CACHED_PTRS\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      T* cur = cachedPtrs_[i];\n      cachedPtrs_[i] = other.cachedPtrs_[i];\n      other.cachedPtrs_[i] = cur;\n    }\n#else\n    (void)other;\n#endif\n  }\n\n  friend class cv::ConVecIterBase<ConcurrentVector<T, Traits>, T>;\n  friend class cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T, false>;\n  friend class cv::ConcurrentVectorIterator<ConcurrentVector<T, Traits>, T, true>;\n};\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator==(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());\n}\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator!=(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return !(a == b);\n}\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator<(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());\n}\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator>(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return b < a;\n}\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator<=(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return !(b < a);\n}\n\ntemplate <typename T, class Traits1, class Traits2>\ninline bool operator>=(\n    const ConcurrentVector<T, Traits1>& a,\n    const ConcurrentVector<T, Traits2>& b) {\n  return !(a < b);\n}\n\ntemplate <typename T, class Traits>\ninline void swap(ConcurrentVector<T, Traits>& a, ConcurrentVector<T, Traits>& b) {\n  a.swap(b);\n}\n\n// Textual inclusion.  Includes undocumented implementation details, e.g. iterators.\n#include <dispenso/detail/concurrent_vector_impl2.h>\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/can_invoke.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <stdint.h>\n\n#include <type_traits>\n#include <utility>\n\nnamespace dispenso {\nnamespace detail {\n\ntemplate <class>\nusing void_t = void;\ntemplate <class Sig, class = void>\nstruct CanInvoke : std::false_type {};\ntemplate <class F, class... Args>\nstruct CanInvoke<F(Args...), void_t<decltype(std::declval<F>()(std::declval<Args>()...))>>\n    : std::true_type {};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/completion_event_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <algorithm>\n#include <atomic>\n#include <chrono>\n\n// Implementation notes:\n// 1. You should know what you're doing if you are directly using CompletionEventImpl.  Most people\n//    should be using CompletionEvent, which is designed for safe use by folks without strong\n//    knowledge of atomics, etc...\n// 2. intrusiveStatus may be used to gain access to the internal atomic status\n// 3. intrusiveStatus may set the status to anything... *but* once wait functions have been called,\n//    if intrusiveStatus sets the status to completedStatus, it should not change the status again.\n//    After notify, the status should not be modified.\n// 4. It is not an error to set the status to completedStatus, and then call notify with\n//    completedStatus, but it is very likely to be unnecessary.  Usually, while there may be threads\n//    racing to get some statuses, and they should use compare_exchange functions to resolve those,\n//    setting completed status should not typically be racy.\n\n#include \"notifier_common.h\"\n\nnamespace dispenso {\nnamespace detail {\n\n#define DISPENSO_COMPLETION_SUPPORTS_TRY_NOTIFY\n\n#if defined(__linux__)\n\nclass CompletionEventImpl {\n public:\n  CompletionEventImpl(int initStatus) : ftx_(initStatus) {}\n\n  void notify(int completedStatus) {\n    status_.store(completedStatus, std::memory_order_release);\n    futex(&ftx_, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max(), nullptr, nullptr, 0);\n  }\n\n  void tryNotify() {\n    futex(&ftx_, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max(), nullptr, nullptr, 0);\n  }\n\n  void wait(int completedStatus) const {\n    int current;\n    while ((current = status_.load(std::memory_order_acquire)) != completedStatus) {\n      futex(&ftx_, FUTEX_WAIT_PRIVATE, current, nullptr, nullptr, 0);\n    }\n  }\n\n  bool waitFor(int completedStatus, const std::chrono::duration<double>& relTime) const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n\n    double relSeconds = relTime.count();\n    if (relSeconds <= 0.0) {\n      return false;\n    }\n\n    struct timespec ts;\n    ts.tv_sec = static_cast<time_t>(relSeconds);\n    relSeconds -= static_cast<double>(ts.tv_sec);\n    ts.tv_nsec = static_cast<long>(1e9 * relSeconds);\n\n    // TODO: determine if we should worry about reducing timeout time subsequent times through the\n    // loop in the case of spurious wake.\n    int current;\n    while ((current = status_.load(std::memory_order_acquire)) != completedStatus) {\n      if (futex(&ftx_, FUTEX_WAIT_PRIVATE, current, &ts, nullptr, 0) && errno == ETIMEDOUT) {\n        // Intentionally not re-checking status: returning false on timeout is consistent with\n        // std::condition_variable::wait_for semantics. The benign race where notify arrives\n        // concurrently with timeout is handled by the caller retrying if needed.\n        return false;\n      }\n    }\n    return true;\n  }\n\n  template <class Clock, class Duration>\n  bool waitUntil(int completedStatus, const std::chrono::time_point<Clock, Duration>& absTime)\n      const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n\n    return waitFor(completedStatus, absTime - Clock::now());\n  }\n\n  std::atomic<int>& intrusiveStatus() {\n    return status_;\n  }\n\n  const std::atomic<int>& intrusiveStatus() const {\n    return status_;\n  }\n\n private:\n  union {\n    mutable int ftx_;\n    std::atomic<int> status_;\n  };\n};\n\n#elif defined(__MACH__) && defined(DISPENSO_HAS_OS_SYNC)\n\n// Uses a 64-bit combined {status, waiterCount} to eliminate the Dekker race between notify() and\n// wait(). notify() atomically sets status while observing waiterCount via CAS; wait() atomically\n// increments waiterCount while observing status via CAS. The 8-byte futex compare detects changes\n// to either field. intrusiveStatus() returns a reference to the status portion (lower 32 bits on\n// little-endian) for direct CAS/fetch_sub by FutureImplBase and Latch.\nclass CompletionEventImpl {\n public:\n  CompletionEventImpl(int initStatus)\n      : combined_(static_cast<uint64_t>(static_cast<uint32_t>(initStatus))) {}\n\n  void notify(int completedStatus) {\n    uint64_t old = combined_.load(std::memory_order_relaxed);\n    uint64_t newVal;\n    do {\n      newVal = (old & kWaiterMask) | static_cast<uint32_t>(completedStatus);\n    } while (!combined_.compare_exchange_weak(\n        old, newVal, std::memory_order_release, std::memory_order_relaxed));\n    if (old & kWaiterMask) {\n      mac_futex_wake_all(&combined_, sizeof(uint64_t));\n    }\n  }\n\n  void tryNotify() {\n    if (combined_.load(std::memory_order_acquire) & kWaiterMask) {\n      mac_futex_wake_all(&combined_, sizeof(uint64_t));\n    }\n  }\n\n  void wait(int completedStatus) const {\n    uint64_t val = combined_.load(std::memory_order_acquire);\n    while (static_cast<int>(val) != completedStatus) {\n      uint64_t newVal = val + kOneWaiter;\n      if (!combined_.compare_exchange_weak(\n              val, newVal, std::memory_order_acq_rel, std::memory_order_acquire)) {\n        continue;\n      }\n      mac_futex_wait(&combined_, newVal, sizeof(uint64_t));\n      combined_.fetch_sub(kOneWaiter, std::memory_order_acq_rel);\n      val = combined_.load(std::memory_order_acquire);\n    }\n  }\n\n  bool waitFor(int completedStatus, const std::chrono::duration<double>& relTime) const {\n    if (static_cast<int>(combined_.load(std::memory_order_acquire)) == completedStatus) {\n      return true;\n    }\n\n    double relSeconds = relTime.count();\n    if (relSeconds <= 0.0) {\n      return false;\n    }\n\n    uint64_t relTimeUs = static_cast<uint64_t>(relSeconds * 1e6);\n\n    // TODO: determine if we should worry about reducing timeout time subsequent times through the\n    // loop in the case of spurious wake.\n    uint64_t val = combined_.load(std::memory_order_acquire);\n    while (static_cast<int>(val) != completedStatus) {\n      uint64_t newVal = val + kOneWaiter;\n      if (!combined_.compare_exchange_weak(\n              val, newVal, std::memory_order_acq_rel, std::memory_order_acquire)) {\n        continue;\n      }\n      int ret = mac_futex_wait_for(&combined_, newVal, sizeof(uint64_t), relTimeUs);\n      combined_.fetch_sub(kOneWaiter, std::memory_order_acq_rel);\n      if (ret && errno == ETIMEDOUT) {\n        // Intentionally not re-checking status: returning false on timeout is consistent with\n        // std::condition_variable::wait_for semantics. The benign race where notify arrives\n        // concurrently with timeout is handled by the caller retrying if needed.\n        return false;\n      }\n      val = combined_.load(std::memory_order_acquire);\n    }\n    return true;\n  }\n\n  template <class Clock, class Duration>\n  bool waitUntil(int completedStatus, const std::chrono::time_point<Clock, Duration>& absTime)\n      const {\n    if (static_cast<int>(combined_.load(std::memory_order_acquire)) == completedStatus) {\n      return true;\n    }\n\n    return waitFor(completedStatus, absTime - Clock::now());\n  }\n\n  std::atomic<int>& intrusiveStatus() {\n    return parts_[0];\n  }\n\n  const std::atomic<int>& intrusiveStatus() const {\n    return parts_[0];\n  }\n\n private:\n  static constexpr uint64_t kOneWaiter = 1ULL << 32;\n  static constexpr uint64_t kWaiterMask = ~0xFFFFFFFFULL;\n\n  union {\n    mutable std::atomic<uint64_t> combined_;\n    mutable std::atomic<int> parts_[2]; // [0] = status (little-endian)\n  };\n};\n\n#elif defined(_WIN32)\n\nclass CompletionEventImpl {\n public:\n  CompletionEventImpl(int initStatus) : status_(initStatus) {}\n\n  void notify(int completedStatus) {\n    status_.store(completedStatus, std::memory_order_release);\n    WakeByAddressAll(&status_);\n  }\n\n  void tryNotify() {\n    WakeByAddressAll(&status_);\n  }\n\n  void wait(int completedStatus) const {\n    int current;\n    while ((current = status_.load(std::memory_order_acquire)) != completedStatus) {\n      WaitOnAddress(&status_, &current, sizeof(int), kInfiniteWin);\n    }\n  }\n\n  bool waitFor(int completedStatus, const std::chrono::duration<double>& relTime) const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n\n    double relSeconds = relTime.count();\n    if (relSeconds <= 0.0) {\n      return false;\n    }\n\n    int msWait = std::max(1, static_cast<int>(relSeconds * 1000.0));\n\n    // TODO: determine if we should worry about reducing timeout time subsequent times through the\n    // loop in the case of spurious wake.\n    int current;\n    while ((current = status_.load(std::memory_order_acquire)) != completedStatus) {\n      if (!WaitOnAddress(&status_, &current, sizeof(int), msWait) &&\n          GetLastError() == kErrorTimeoutWin) {\n        // Intentionally not re-checking status: returning false on timeout is consistent with\n        // std::condition_variable::wait_for semantics. The benign race where notify arrives\n        // concurrently with timeout is handled by the caller retrying if needed.\n        return false;\n      }\n    }\n    return true;\n  }\n\n  template <class Clock, class Duration>\n  bool waitUntil(int completedStatus, const std::chrono::time_point<Clock, Duration>& absTime)\n      const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n\n    return waitFor(completedStatus, absTime - Clock::now());\n  }\n\n  std::atomic<int>& intrusiveStatus() {\n    return status_;\n  }\n\n  const std::atomic<int>& intrusiveStatus() const {\n    return status_;\n  }\n\n private:\n  mutable std::atomic<int> status_;\n};\n\n#else\n\n#undef DISPENSO_COMPLETION_SUPPORTS_TRY_NOTIFY\n\n// Fallback C++11 implementation.\nclass CompletionEventImpl {\n public:\n  CompletionEventImpl(int initStatus) : status_(initStatus) {}\n\n  void notify(int completedStatus) {\n    // See https://en.cppreference.com/w/cpp/thread/condition_variable\n    // \"Even if the shared variable is atomic, it must be modified under the mutex in order to\n    // correctly publish the modification to the waiting thread.\"\n    {\n      std::lock_guard<std::mutex> lk(mtx_);\n      status_.store(completedStatus, std::memory_order_release);\n    }\n    cv_.notify_all();\n  }\n\n  void wait(int completedStatus) const {\n    if (status_.load(std::memory_order_acquire) != completedStatus) {\n      std::unique_lock<std::mutex> lk(mtx_);\n      cv_.wait(lk, [this, completedStatus]() {\n        return status_.load(std::memory_order_relaxed) == completedStatus;\n      });\n    }\n  }\n\n  template <class Rep, class Period>\n  bool waitFor(int completedStatus, const std::chrono::duration<Rep, Period>& relTime) const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n    std::unique_lock<std::mutex> lk(mtx_);\n    return cv_.wait_for(lk, relTime, [this, completedStatus] {\n      return status_.load(std::memory_order_relaxed) == completedStatus;\n    });\n  }\n\n  template <class Clock, class Duration>\n  bool waitUntil(int completedStatus, const std::chrono::time_point<Clock, Duration>& absTime)\n      const {\n    if (status_.load(std::memory_order_acquire) == completedStatus) {\n      return true;\n    }\n    std::unique_lock<std::mutex> lk(mtx_);\n    return cv_.wait_until(lk, absTime, [this, completedStatus] {\n      return status_.load(std::memory_order_relaxed) == completedStatus;\n    });\n  }\n\n  std::atomic<int>& intrusiveStatus() {\n    return status_;\n  }\n\n  const std::atomic<int>& intrusiveStatus() const {\n    return status_;\n  }\n\n private:\n  mutable std::mutex mtx_;\n  mutable std::condition_variable cv_;\n  std::atomic<int> status_;\n};\n#endif // platform\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/concurrent_vector_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file intended for textual inclusion into concurrent_vector.h only\n\nnamespace cv {\n\nstruct BucketInfo {\n  size_t bucket;\n  size_t bucketIndex;\n  size_t bucketCapacity;\n};\n\ntemplate <typename VecT, typename T>\nclass ConVecIterBase {\n public:\n  using iterator_category = std::random_access_iterator_tag;\n  using difference_type = ssize_t;\n  using value_type = T;\n\n  ConVecIterBase() = default;\n  ConVecIterBase(const VecT* vec, BucketInfo info);\n\n protected:\n  ConVecIterBase(uintptr_t vb, T* bucketStart, T* bucketPtr, T* bucketEnd)\n      : vb_(vb), bucketStart_(bucketStart), bucketPtr_(bucketPtr), bucketEnd_(bucketEnd) {}\n\n  struct VecAndBucket {\n    const VecT* vec;\n    const size_t bucket;\n  };\n  VecAndBucket getVecAndBucket() const {\n    static_assert(\n        alignof(VecT) >= 64,\n        \"This code relies on the ConcurrentVector pointer to be 64-byte aligned\");\n    if (sizeof(uintptr_t) == 8) {\n      return {reinterpret_cast<const VecT*>(vb_ & 0xffffffffffffffc0UL), vb_ & 0x3f};\n    } else {\n      return {reinterpret_cast<const VecT*>(vb_ & 0xffffffc0), vb_ & 0x3f};\n    }\n  }\n\n  // Note: Could have a size-optimized iterator via traits.  It is easy to reduce this to 24 bytes\n  // on 64-bit platform, but this will result in a large enough performance hit that storing an\n  // index is preferable (see CompactCVecIterator).  16 bytes on 32-bit platform.\n  alignas(4 * sizeof(uintptr_t)) uintptr_t vb_;\n  T* bucketStart_;\n  T* bucketPtr_;\n  T* bucketEnd_;\n\n private:\n  friend bool operator!=(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.bucketPtr_ != b.bucketPtr_;\n  }\n  friend bool operator==(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.bucketPtr_ == b.bucketPtr_;\n  }\n  friend bool operator<(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.vb_ < b.vb_ || (a.vb_ == b.vb_ && a.bucketPtr_ < b.bucketPtr_);\n  }\n  friend bool operator<=(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.vb_ < b.vb_ || (a.vb_ == b.vb_ && a.bucketPtr_ <= b.bucketPtr_);\n  }\n  friend bool operator>(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.vb_ > b.vb_ || (a.vb_ == b.vb_ && a.bucketPtr_ > b.bucketPtr_);\n  }\n  friend bool operator>=(const ConVecIterBase& a, const ConVecIterBase& b) {\n    return a.vb_ > b.vb_ || (a.vb_ == b.vb_ && a.bucketPtr_ >= b.bucketPtr_);\n  }\n\n  friend difference_type operator-(const ConVecIterBase& a, const ConVecIterBase& b) {\n    size_t abucket = a.vb_ & 0x3f;\n    size_t bbucket = b.vb_ & 0x3f;\n\n    if (abucket == bbucket) {\n      return a.bucketPtr_ - b.bucketPtr_;\n    }\n\n    ssize_t aLeft = a.bucketPtr_ - a.bucketStart_;\n    ssize_t bLeft = b.bucketPtr_ - b.bucketStart_;\n\n    aLeft += (bool)abucket * (a.bucketEnd_ - a.bucketStart_);\n    bLeft += (bool)bbucket * (b.bucketEnd_ - b.bucketStart_);\n\n    return aLeft - bLeft;\n  }\n};\n\ntemplate <typename VecT, typename T, bool kIsConst>\nclass ConcurrentVectorIterator : public ConVecIterBase<VecT, T> {\n public:\n  using iterator_category = typename ConVecIterBase<VecT, T>::iterator_category;\n  using difference_type = typename ConVecIterBase<VecT, T>::difference_type;\n  using value_type = typename ConVecIterBase<VecT, T>::value_type;\n  using pointer = std::conditional_t<kIsConst, std::add_const_t<T*>, T*>;\n  using reference = std::conditional_t<kIsConst, std::add_const_t<T&>, T&>;\n\n  ConcurrentVectorIterator() = default;\n\n  ConcurrentVectorIterator(const VecT* vec, BucketInfo info) : ConVecIterBase<VecT, T>(vec, info) {}\n  ConcurrentVectorIterator(const VecT* vec, size_t /*index*/, BucketInfo info)\n      : ConcurrentVectorIterator(vec, info) {}\n\n  template <bool kWasConst, typename = std::enable_if_t<kIsConst && !kWasConst>>\n  ConcurrentVectorIterator(const ConcurrentVectorIterator<VecT, T, kWasConst>& other)\n      : ConVecIterBase<VecT, T>(other) {}\n\n  reference operator*() const;\n  pointer operator->() const;\n\n  reference operator[](difference_type n) const;\n\n  ConcurrentVectorIterator& operator++();\n\n  ConcurrentVectorIterator operator++(int) {\n    auto result = *this;\n    operator++();\n    return result;\n  }\n\n  ConcurrentVectorIterator& operator--();\n\n  ConcurrentVectorIterator operator--(int) {\n    auto result = *this;\n    operator--();\n    return result;\n  }\n\n  ConcurrentVectorIterator& operator+=(difference_type n);\n  ConcurrentVectorIterator& operator-=(difference_type n) {\n    return operator+=(-n);\n  }\n\n  ConcurrentVectorIterator operator+(difference_type n) const;\n  ConcurrentVectorIterator operator-(difference_type n) const {\n    return operator+(-n);\n  }\n\n private:\n  ConcurrentVectorIterator(uintptr_t vb, T* bucketStart, T* bucketPtr, T* bucketEnd)\n      : ConVecIterBase<VecT, T>(vb, bucketStart, bucketPtr, bucketEnd) {}\n\n  using ConVecIterBase<VecT, T>::getVecAndBucket;\n\n  using ConVecIterBase<VecT, T>::vb_;\n  using ConVecIterBase<VecT, T>::bucketStart_;\n  using ConVecIterBase<VecT, T>::bucketPtr_;\n  using ConVecIterBase<VecT, T>::bucketEnd_;\n};\n\ntemplate <typename VecT, typename T>\nclass CompactCVecIterBase {\n public:\n  using iterator_category = std::random_access_iterator_tag;\n  using difference_type = ssize_t;\n  using value_type = T;\n\n  CompactCVecIterBase() = default;\n\n  CompactCVecIterBase(const VecT* vec, size_t index) : vec_(vec), index_(index) {}\n\n protected:\n  // 16 bytes on 64-bit platform, 8 bytes on 32-bit platform.\n  const VecT* vec_;\n  size_t index_;\n\n private:\n  friend bool operator!=(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ != b.index_;\n  }\n  friend bool operator==(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ == b.index_;\n  }\n  friend bool operator<(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ < b.index_;\n  }\n  friend bool operator<=(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ <= b.index_;\n  }\n  friend bool operator>(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ > b.index_;\n  }\n  friend bool operator>=(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ >= b.index_;\n  }\n\n  friend difference_type operator-(const CompactCVecIterBase& a, const CompactCVecIterBase& b) {\n    return a.index_ - b.index_;\n  }\n};\n\ntemplate <typename VecT, typename T, bool kIsConst>\nclass CompactCVecIterator : public CompactCVecIterBase<VecT, T> {\n public:\n  using difference_type = ssize_t;\n  using value_type = T;\n  using pointer = std::conditional_t<kIsConst, std::add_const_t<T*>, T*>;\n  using reference = std::conditional_t<kIsConst, std::add_const_t<T&>, T&>;\n  using iterator_category = std::random_access_iterator_tag;\n\n  CompactCVecIterator() = default;\n\n  CompactCVecIterator(const VecT* vec, size_t index, BucketInfo)\n      : CompactCVecIterator(vec, index) {}\n  CompactCVecIterator(const VecT* vec, size_t index) : CompactCVecIterBase<VecT, T>(vec, index) {}\n  template <bool kWasConst, typename = std::enable_if_t<kIsConst && !kWasConst>>\n  CompactCVecIterator(const CompactCVecIterator<VecT, T, kWasConst>& other)\n      : CompactCVecIterBase<VecT, T>(other) {}\n  reference operator*() const;\n  pointer operator->() const;\n\n  reference operator[](difference_type n) const;\n\n  CompactCVecIterator& operator++() {\n    ++index_;\n    return *this;\n  }\n\n  CompactCVecIterator operator++(int) {\n    auto result = *this;\n    operator++();\n    return result;\n  }\n\n  CompactCVecIterator& operator--() {\n    --index_;\n    return *this;\n  }\n\n  CompactCVecIterator operator--(int) {\n    auto result = *this;\n    operator--();\n    return result;\n  }\n\n  CompactCVecIterator& operator+=(difference_type n) {\n    index_ += n;\n    return *this;\n  }\n  CompactCVecIterator& operator-=(difference_type n) {\n    return operator+=(-n);\n  }\n\n  CompactCVecIterator operator+(difference_type n) const {\n    return {vec_, index_ + n};\n  }\n  CompactCVecIterator operator-(difference_type n) const {\n    return operator+(-n);\n  }\n\n private:\n  using CompactCVecIterBase<VecT, T>::vec_;\n  using CompactCVecIterBase<VecT, T>::index_;\n};\n\ntemplate <typename T>\ninline T* alloc(size_t elts) {\n  return reinterpret_cast<T*>(detail::alignedMalloc(elts * sizeof(T), alignof(T)));\n}\n\ntemplate <typename T>\ninline void dealloc(T* p) {\n  detail::alignedFree(p);\n}\n\ntemplate <typename T, size_t kMinBufferSize, size_t kMaxVectorSize, bool kMakeInline>\nclass ConVecBufferBase {};\n\ntemplate <typename T, size_t kMinBufferSize, size_t kMaxVectorSize>\nclass ConVecBufferBase<T, kMinBufferSize, kMaxVectorSize, false> {\n public:\n  static constexpr size_t kMaxBuffers = detail::log2const(kMaxVectorSize / kMinBufferSize) + 1;\n\n  ConVecBufferBase() : buffers_(alloc<detail::AlignedAtomic<T>>(kMaxBuffers)) {\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      buffers_[i].store(nullptr, std::memory_order_relaxed);\n    }\n  }\n\n  ~ConVecBufferBase() {\n    dealloc<detail::AlignedAtomic<T>>(buffers_);\n  }\n\n  ConVecBufferBase(ConVecBufferBase&& other)\n      : buffers_(std::exchange(other.buffers_, alloc<detail::AlignedAtomic<T>>(kMaxBuffers))) {\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      other.buffers_[i].store(nullptr, std::memory_order_relaxed);\n    }\n  }\n\n  ConVecBufferBase& operator=(ConVecBufferBase&& other) {\n    using std::swap;\n    swap(other.buffers_, buffers_);\n    return *this;\n  }\n\n protected:\n  detail::AlignedAtomic<T>* buffers_;\n};\n\ntemplate <typename T, size_t kMinBufferSize, size_t kMaxVectorSize>\nclass ConVecBufferBase<T, kMinBufferSize, kMaxVectorSize, true> {\n public:\n  static constexpr size_t kMaxBuffers = detail::log2const(kMaxVectorSize / kMinBufferSize) + 1;\n\n  ConVecBufferBase() {\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      buffers_[i].store(nullptr, std::memory_order_relaxed);\n    }\n  }\n  ConVecBufferBase(ConVecBufferBase&& other) {\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      buffers_[i].store(\n          other.buffers_[i].load(std::memory_order_relaxed), std::memory_order_relaxed);\n      other.buffers_[i].store(nullptr, std::memory_order_relaxed);\n    }\n  }\n\n  ConVecBufferBase& operator=(ConVecBufferBase&& other) {\n    for (size_t i = 0; i < kMaxBuffers; ++i) {\n      T* cur = buffers_[i].load(std::memory_order_relaxed);\n      T* oth = other.buffers_[i].load(std::memory_order_relaxed);\n\n      buffers_[i].store(oth, std::memory_order_relaxed);\n      other.buffers_[i].store(cur, std::memory_order_relaxed);\n    }\n    return *this;\n  }\n\n protected:\n  detail::AlignedAtomic<T> buffers_[kMaxBuffers];\n};\n\ntemplate <\n    typename T,\n    size_t kMinBufferSize,\n    size_t kMaxVectorSize,\n    bool kMakeInline,\n    ConcurrentVectorReallocStrategy kStrategy>\nclass ConVecBuffer : public ConVecBufferBase<T, kMinBufferSize, kMaxVectorSize, kMakeInline> {\n public:\n  ConVecBuffer() {\n    std::memset(shouldDealloc_, 0, BaseType::kMaxBuffers * sizeof(bool));\n  }\n\n  ConVecBuffer(ConVecBuffer&& other) : BaseType(std::move(other)) {\n    std::memcpy(shouldDealloc_, other.shouldDealloc_, BaseType::kMaxBuffers * sizeof(bool));\n    std::memset(other.shouldDealloc_, 0, BaseType::kMaxBuffers * sizeof(bool));\n  }\n\n  ConVecBuffer& operator=(ConVecBuffer&& other) {\n    if (&other != this) {\n      BaseType::operator=(std::move(other));\n      std::swap_ranges(\n          other.shouldDealloc_, other.shouldDealloc_ + BaseType::kMaxBuffers, shouldDealloc_);\n    }\n    return *this;\n  }\n\n  detail::AlignedAtomic<T>& operator[](size_t bucket) {\n    return this->buffers_[bucket];\n  }\n\n  const detail::AlignedAtomic<T>& operator[](size_t bucket) const {\n    return this->buffers_[bucket];\n  }\n\n  void allocAsNecessary(const BucketInfo& binfo) {\n    allocAsNecessaryImpl(binfo, [](size_t, T*) {});\n  }\n\n  void allocAsNecessary(const BucketInfo& binfo, T** cachedPtrs) {\n    allocAsNecessaryImpl(binfo, [cachedPtrs](size_t b, T* p) { cachedPtrs[b] = p; });\n  }\n\n  void allocAsNecessary(const BucketInfo& binfo, ssize_t rangeLen, const BucketInfo& bend) {\n    allocAsNecessaryImpl(binfo, rangeLen, bend, [](size_t, T*) {});\n  }\n\n  void allocAsNecessary(\n      const BucketInfo& binfo,\n      ssize_t rangeLen,\n      const BucketInfo& bend,\n      T** cachedPtrs) {\n    allocAsNecessaryImpl(\n        binfo, rangeLen, bend, [cachedPtrs](size_t b, T* p) { cachedPtrs[b] = p; });\n  }\n\n  bool shouldDealloc(size_t bucket) const {\n    return shouldDealloc_[bucket];\n  }\n\n private:\n  using BaseType = ConVecBufferBase<T, kMinBufferSize, kMaxVectorSize, kMakeInline>;\n\n  DISPENSO_INLINE static size_t allocCheckIndex(size_t bucketCapacity) {\n    return (kStrategy == ConcurrentVectorReallocStrategy::kFullBufferAhead)\n        ? 0\n        : (kStrategy == ConcurrentVectorReallocStrategy::kHalfBufferAhead ? bucketCapacity / 2\n                                                                          : bucketCapacity - 1);\n  }\n\n  template <typename CacheUpdate>\n  void allocAsNecessaryImpl(const BucketInfo& binfo, CacheUpdate&& cacheUpdate) {\n    if (DISPENSO_EXPECT(binfo.bucketIndex == allocCheckIndex(binfo.bucketCapacity), 0)) {\n      if (!this->buffers_[binfo.bucket + 1].load(std::memory_order_acquire)) {\n        T* newBuf = cv::alloc<T>(binfo.bucketCapacity << 1);\n        cacheUpdate(binfo.bucket + 1, newBuf);\n        this->buffers_[binfo.bucket + 1].store(newBuf, std::memory_order_release);\n        shouldDealloc_[binfo.bucket + 1] = true;\n      }\n    }\n    while (DISPENSO_EXPECT(!this->buffers_[binfo.bucket].load(std::memory_order_acquire), 0)) {\n    }\n  }\n\n  template <typename CacheUpdate>\n  DISPENSO_INLINE bool tryAssignBuffer(\n      size_t bucket,\n      T*& allocBufs,\n      size_t cap,\n      bool firstAccounted,\n      CacheUpdate&& cacheUpdate) {\n    if (!this->buffers_[bucket].load(std::memory_order_acquire)) {\n      cacheUpdate(bucket, allocBufs);\n      this->buffers_[bucket].store(allocBufs, std::memory_order_release);\n      allocBufs += cap;\n      shouldDealloc_[bucket] = !firstAccounted;\n      return true;\n    }\n    return false;\n  }\n\n  template <typename CacheUpdate>\n  void allocAsNecessaryImpl(\n      const BucketInfo& binfo,\n      ssize_t rangeLen,\n      const BucketInfo& bend,\n      CacheUpdate&& cacheUpdate) {\n    const size_t indexToCheck = allocCheckIndex(binfo.bucketCapacity);\n\n    bool allocCurrentBucket =\n        binfo.bucketIndex <= indexToCheck && binfo.bucketIndex + rangeLen > indexToCheck;\n    if (DISPENSO_EXPECT(allocCurrentBucket || binfo.bucket < bend.bucket, 0)) {\n      size_t sizeToAlloc = 0;\n\n      size_t cap = binfo.bucketCapacity << ((bool)binfo.bucket + !allocCurrentBucket);\n      size_t bucket = binfo.bucket + 1 + !allocCurrentBucket;\n      for (; bucket <= bend.bucket; ++bucket, cap <<= 1) {\n        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {\n          sizeToAlloc += cap;\n        }\n      }\n\n      assert(bucket == bend.bucket + 1);\n      assert((bucket == 1 && cap == bend.bucketCapacity) || cap == bend.bucketCapacity * 2);\n\n      const size_t endToCheck = allocCheckIndex(bend.bucketCapacity);\n\n      if (DISPENSO_EXPECT(bend.bucketIndex > endToCheck, 0)) {\n        if (!this->buffers_[bucket].load(std::memory_order_acquire)) {\n          sizeToAlloc += cap;\n        }\n      }\n\n      T* allocBufs = nullptr;\n      if (sizeToAlloc) {\n        allocBufs = cv::alloc<T>(sizeToAlloc);\n      }\n      bool firstAccounted = false;\n\n      cap = binfo.bucketCapacity << ((bool)binfo.bucket + !allocCurrentBucket);\n      bucket = binfo.bucket + 1 + !allocCurrentBucket;\n      for (; bucket <= bend.bucket; ++bucket, cap <<= 1) {\n        firstAccounted |= tryAssignBuffer(bucket, allocBufs, cap, firstAccounted, cacheUpdate);\n      }\n\n      assert(bucket == bend.bucket + 1);\n      assert((bucket == 1 && cap == bend.bucketCapacity) || cap == bend.bucketCapacity * 2);\n\n      if (DISPENSO_EXPECT(bend.bucketIndex > endToCheck, 0)) {\n        tryAssignBuffer(bucket, allocBufs, cap, firstAccounted, cacheUpdate);\n      }\n    }\n    for (size_t bucket = binfo.bucket; bucket <= bend.bucket; ++bucket) {\n      while (DISPENSO_EXPECT(!this->buffers_[bucket].load(std::memory_order_acquire), 0)) {\n#if defined(DISPENSO_HAS_TSAN)\n        std::this_thread::sleep_for(std::chrono::microseconds(1));\n#endif // DISPENSO_HAS_TSAN\n      }\n    }\n  }\n\n  bool shouldDealloc_[BaseType::kMaxBuffers];\n};\n\n} // namespace cv\n"
  },
  {
    "path": "dispenso/detail/concurrent_vector_impl2.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This file intended for textual inclusion into concurrent_vector.h only\n\nnamespace cv {\n\ntemplate <typename VecT, typename T>\nDISPENSO_INLINE ConVecIterBase<VecT, T>::ConVecIterBase(const VecT* vec, cv::BucketInfo info)\n    : vb_(reinterpret_cast<uintptr_t>(vec) | info.bucket),\n      bucketStart_(vec->buffers_[info.bucket].load(std::memory_order_relaxed)),\n      bucketPtr_(bucketStart_ + info.bucketIndex),\n      bucketEnd_(bucketStart_ + info.bucketCapacity) {}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE ConcurrentVectorIterator<VecT, T, kIsConst>&\nConcurrentVectorIterator<VecT, T, kIsConst>::operator++() {\n  ++bucketPtr_;\n  if (bucketPtr_ == bucketEnd_) {\n    auto len = bucketEnd_ - bucketStart_;\n    ++vb_;\n    auto vb = getVecAndBucket();\n    len <<= int{vb.bucket > 1};\n    bucketPtr_ = bucketStart_ = vb.vec->cachedBuffer(vb.bucket);\n    bucketEnd_ = bucketPtr_ + len;\n  }\n  return *this;\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE ConcurrentVectorIterator<VecT, T, kIsConst>&\nConcurrentVectorIterator<VecT, T, kIsConst>::operator--() {\n  --bucketPtr_;\n  if (bucketPtr_ < bucketStart_) {\n    auto vb = getVecAndBucket();\n    if (vb.bucket) {\n      auto len = bucketEnd_ - bucketStart_;\n      --vb_;\n      len >>= int{vb.bucket > 1};\n      bucketStart_ = vb.vec->cachedBuffer(vb.bucket - 1);\n      bucketPtr_ = bucketStart_ + len;\n      bucketEnd_ = bucketPtr_;\n      --bucketPtr_;\n    }\n  }\n  return *this;\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename ConcurrentVectorIterator<VecT, T, kIsConst>::reference\nConcurrentVectorIterator<VecT, T, kIsConst>::operator*() const {\n  return *bucketPtr_;\n}\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename ConcurrentVectorIterator<VecT, T, kIsConst>::pointer\nConcurrentVectorIterator<VecT, T, kIsConst>::operator->() const {\n  return &operator*();\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename ConcurrentVectorIterator<VecT, T, kIsConst>::reference\nConcurrentVectorIterator<VecT, T, kIsConst>::operator[](difference_type n) const {\n  T* nPtr = bucketPtr_ + n;\n  if (nPtr >= bucketStart_ && nPtr < bucketEnd_) {\n    return *nPtr;\n  }\n\n  auto vb = getVecAndBucket();\n\n  // Reconstruct index\n  ssize_t oldIndex = bucketPtr_ - bucketStart_;\n  oldIndex += (bool)vb.bucket * (bucketEnd_ - bucketStart_);\n  auto binfo = vb.vec->bucketAndSubIndexForIndex(oldIndex + n);\n  return *(vb.vec->cachedBuffer(binfo.bucket) + binfo.bucketIndex);\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE ConcurrentVectorIterator<VecT, T, kIsConst>&\nConcurrentVectorIterator<VecT, T, kIsConst>::operator+=(difference_type n) {\n  T* nPtr = bucketPtr_ + n;\n  if (nPtr >= bucketStart_ && nPtr < bucketEnd_) {\n    bucketPtr_ = nPtr;\n    return *this;\n  }\n\n  auto vb = getVecAndBucket();\n\n  // Reconstruct index\n  ssize_t oldIndex = bucketPtr_ - bucketStart_;\n  oldIndex += (bool)vb.bucket * (bucketEnd_ - bucketStart_);\n  auto binfo = vb.vec->bucketAndSubIndexForIndex(oldIndex + n);\n  bucketStart_ = vb.vec->cachedBuffer(binfo.bucket);\n  bucketEnd_ = bucketStart_ + binfo.bucketCapacity;\n  bucketPtr_ = bucketStart_ + binfo.bucketIndex;\n  vb_ = reinterpret_cast<uintptr_t>(vb.vec) | binfo.bucket;\n  return *this;\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE ConcurrentVectorIterator<VecT, T, kIsConst>\nConcurrentVectorIterator<VecT, T, kIsConst>::operator+(difference_type n) const {\n  T* nPtr = bucketPtr_ + n;\n  if (nPtr >= bucketStart_ && nPtr < bucketEnd_) {\n    return {vb_, bucketStart_, nPtr, bucketEnd_};\n  }\n\n  auto vb = getVecAndBucket();\n  // Reconstruct index\n  ssize_t oldIndex = bucketPtr_ - bucketStart_;\n  oldIndex += (bool)vb.bucket * (bucketEnd_ - bucketStart_);\n  auto binfo = vb.vec->bucketAndSubIndexForIndex(oldIndex + n);\n  return {vb.vec, binfo};\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename CompactCVecIterator<VecT, T, kIsConst>::reference\nCompactCVecIterator<VecT, T, kIsConst>::operator*() const {\n  return const_cast<VecT&>(*vec_)[index_];\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename CompactCVecIterator<VecT, T, kIsConst>::pointer\nCompactCVecIterator<VecT, T, kIsConst>::operator->() const {\n  return &operator*();\n}\n\ntemplate <typename VecT, typename T, bool kIsConst>\nDISPENSO_INLINE typename CompactCVecIterator<VecT, T, kIsConst>::reference\nCompactCVecIterator<VecT, T, kIsConst>::operator[](ssize_t n) const {\n  return const_cast<VecT&>(*vec_)[index_ + n];\n}\n} // namespace cv\n"
  },
  {
    "path": "dispenso/detail/epoch_waiter.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <algorithm>\n#include <atomic>\n#include <chrono>\n\n#include \"notifier_common.h\"\n\nnamespace dispenso {\nnamespace detail {\n\n#if defined(__linux__)\n\nclass EpochWaiter {\n public:\n  EpochWaiter() : ftx_(0) {}\n\n  void bumpAndWake() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    futex(&ftx_, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);\n  }\n\n  void bumpAndWakeAll() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    futex(&ftx_, FUTEX_WAKE_PRIVATE, std::numeric_limits<int>::max(), nullptr, nullptr, 0);\n  }\n\n  void bumpAndWakeN(int n, int totalWaiters) {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    (void)totalWaiters;\n    futex(&ftx_, FUTEX_WAKE_PRIVATE, n, nullptr, nullptr, 0);\n  }\n\n  uint32_t wait(uint32_t expectedEpoch) const {\n    uint32_t current;\n    // allow spurious wakeups\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      futex(&ftx_, FUTEX_WAIT_PRIVATE, expectedEpoch, nullptr, nullptr, 0);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t current() const {\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t waitFor(uint32_t expectedEpoch, uint64_t relTimeUs) const {\n    uint32_t current;\n    if ((current = epoch_.load(std::memory_order_acquire)) != expectedEpoch) {\n      return current;\n    }\n\n    struct timespec ts;\n    ts.tv_sec = static_cast<decltype(ts.tv_sec)>(relTimeUs / 1000000);\n    ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((relTimeUs - (ts.tv_sec * 1000000)) * 1000);\n\n    // allow spurious wakeups\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      futex(&ftx_, FUTEX_WAIT_PRIVATE, current, &ts, nullptr, 0);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n private:\n  union {\n    mutable int ftx_;\n    std::atomic<uint32_t> epoch_;\n  };\n};\n\n#elif defined(__MACH__) && defined(DISPENSO_HAS_MAC_FUTEX)\n\nclass EpochWaiter {\n public:\n  EpochWaiter() : epoch_(0) {}\n\n  void bumpAndWake() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    mac_futex_wake_one(&epoch_, sizeof(uint32_t));\n  }\n\n  void bumpAndWakeAll() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    mac_futex_wake_all(&epoch_, sizeof(uint32_t));\n  }\n\n  void bumpAndWakeN(int n, int totalWaiters) {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    if (n >= totalWaiters) {\n      mac_futex_wake_all(&epoch_, sizeof(uint32_t));\n    } else {\n      for (int i = 0; i < n; ++i) {\n        mac_futex_wake_one(&epoch_, sizeof(uint32_t));\n      }\n    }\n  }\n\n  uint32_t wait(uint32_t expectedEpoch) const {\n    uint32_t current;\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      mac_futex_wait(&epoch_, expectedEpoch, sizeof(uint32_t));\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t current() const {\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t waitFor(uint32_t expectedEpoch, uint64_t relTimeUs) const {\n    uint32_t current;\n    if ((current = epoch_.load(std::memory_order_acquire)) != expectedEpoch) {\n      return current;\n    }\n\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      mac_futex_wait_for(&epoch_, current, sizeof(uint32_t), relTimeUs);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n private:\n  mutable std::atomic<uint32_t> epoch_;\n};\n\n#elif defined(_WIN32)\n\nclass EpochWaiter {\n public:\n  EpochWaiter() : epoch_(0) {}\n\n  void bumpAndWake() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    // Always WakeAll on Windows. WakeByAddressSingle and WakeByAddressAll\n    // have comparable per-call kernel cost, but WakeAll keeps more threads\n    // in their spin phase (kBackoffYield iterations) where they can pick up\n    // subsequent work without another kernel wake transition.\n    WakeByAddressAll(&epoch_);\n  }\n\n  void bumpAndWakeAll() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    WakeByAddressAll(&epoch_);\n  }\n\n  void bumpAndWakeN(int /*n*/, int totalWaiters) {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    // Only use WakeByAddressSingle when there is exactly one waiter —\n    // it avoids waking threads that aren't waiting. Otherwise, WakeAll\n    // is preferred: same single kernel transition, and keeps threads\n    // spinning where they can absorb follow-up work without re-waking.\n    if (totalWaiters <= 1) {\n      WakeByAddressSingle(&epoch_);\n    } else {\n      WakeByAddressAll(&epoch_);\n    }\n  }\n\n  uint32_t wait(uint32_t expectedEpoch) const {\n    uint32_t current;\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      WaitOnAddress(&epoch_, &current, sizeof(uint32_t), kInfiniteWin);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t current() const {\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t waitFor(uint32_t expectedEpoch, uint64_t relTimeUs) const {\n    uint32_t current;\n    if ((current = epoch_.load(std::memory_order_acquire)) != expectedEpoch) {\n      return current;\n    }\n\n    // WaitOnAddress takes DWORD (unsigned long) milliseconds.\n    // Clamp to the largest finite timeout to avoid overflow or\n    // accidentally passing INFINITE (0xFFFFFFFF = wait forever).\n    uint64_t msVal = std::max(uint64_t{1}, relTimeUs / 1000);\n    unsigned long msWait = msVal >= kInfiniteWin ? static_cast<unsigned long>(kInfiniteWin - 1)\n                                                 : static_cast<unsigned long>(msVal);\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      WaitOnAddress(&epoch_, &current, sizeof(uint32_t), msWait);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n private:\n  mutable std::atomic<uint32_t> epoch_;\n};\n\n#else\n\n// Fallback C++11 implementation.\nclass EpochWaiter {\n public:\n  EpochWaiter() : epoch_(0) {}\n\n  void bumpAndWake() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    cv_.notify_one();\n  }\n\n  void bumpAndWakeAll() {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    cv_.notify_all();\n  }\n\n  void bumpAndWakeN(int n, int totalWaiters) {\n    epoch_.fetch_add(1, std::memory_order_acq_rel);\n    if (n >= totalWaiters) {\n      cv_.notify_all();\n    } else {\n      for (int i = 0; i < n; ++i) {\n        cv_.notify_one();\n      }\n    }\n  }\n\n  uint32_t wait(uint32_t expectedEpoch) const {\n    uint32_t current;\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      std::unique_lock<std::mutex> lk(mtx_);\n      cv_.wait(lk);\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t current() const {\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n  uint32_t waitFor(uint32_t expectedEpoch, uint64_t relTimeUs) const {\n    uint32_t current;\n    if ((current = epoch_.load(std::memory_order_acquire)) != expectedEpoch) {\n      return current;\n    }\n\n    // Allow spurious wake\n    if ((current = epoch_.load(std::memory_order_acquire)) == expectedEpoch) {\n      std::unique_lock<std::mutex> lk(mtx_);\n      cv_.wait_for(lk, std::chrono::microseconds(static_cast<int64_t>(relTimeUs)));\n    } else {\n      return current;\n    }\n    return epoch_.load(std::memory_order_acquire);\n  }\n\n private:\n  mutable std::mutex mtx_;\n  mutable std::condition_variable cv_;\n  std::atomic<uint32_t> epoch_;\n};\n\n#endif // platform\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/future_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <future>\n\n#include <dispenso/completion_event.h>\n#include <dispenso/once_function.h>\n#include <dispenso/task_set.h>\n\nnamespace dispenso {\nnamespace detail {\n\ntemplate <typename Result>\nclass FutureImplResultMember {\n public:\n  Result& result() const {\n#if defined(__cpp_exceptions)\n    if (exception_) {\n      std::rethrow_exception(exception_);\n    }\n#endif // __cpp_exceptions\n    return *reinterpret_cast<Result*>(resultBuf_);\n  }\n\n  ~FutureImplResultMember() {\n#if defined(__cpp_exceptions)\n    // We don't want to call the destructor if we never set the result.\n    if (exception_) {\n      return;\n    }\n#endif // __cpp_exceptions\n\n    reinterpret_cast<Result*>(resultBuf_)->~Result();\n  }\n\n protected:\n  template <typename Func>\n  void runToResult(Func&& f) {\n#if defined(__cpp_exceptions)\n    try {\n      new (resultBuf_) Result(f());\n    } catch (...) {\n      exception_ = std::current_exception();\n    }\n#else\n    new (resultBuf_) Result(f());\n#endif // __cpp_exceptions\n  }\n\n  template <typename T>\n  void setAsResult(T&& t) {\n    new (resultBuf_) Result(std::forward<T>(t));\n  }\n\n  alignas(Result) mutable char resultBuf_[sizeof(Result)];\n\n  // Always present to ensure stable ABI layout regardless of __cpp_exceptions.\n  std::exception_ptr exception_;\n};\n\ntemplate <typename Result>\nclass FutureImplResultMember<Result&> {\n protected:\n  template <typename Func>\n  void runToResult(Func&& f) {\n#if defined(__cpp_exceptions)\n    try {\n      result_ = &f();\n    } catch (...) {\n      exception_ = std::current_exception();\n    }\n#else\n    result_ = &f();\n#endif // __cpp_exceptions\n  }\n\n  Result& result() const {\n#if defined(__cpp_exceptions)\n    if (exception_) {\n      std::rethrow_exception(exception_);\n    }\n#endif // __cpp_exceptions\n    return *result_;\n  }\n\n  void setAsResult(Result* res) {\n    result_ = res;\n  }\n\n  Result* result_;\n\n  // Always present to ensure stable ABI layout regardless of __cpp_exceptions.\n  std::exception_ptr exception_;\n};\n\ntemplate <>\nclass FutureImplResultMember<void> {\n protected:\n  template <typename Func>\n  void runToResult(Func&& f) {\n#if defined(__cpp_exceptions)\n    try {\n      f();\n    } catch (...) {\n      exception_ = std::current_exception();\n    }\n#else\n    f();\n#endif // __cpp_exceptions\n  }\n  void result() const {\n#if defined(__cpp_exceptions)\n    if (exception_) {\n      std::rethrow_exception(exception_);\n    }\n#endif // __cpp_exceptions\n  }\n  void setAsResult() const {}\n\n  // Always present to ensure stable ABI layout regardless of __cpp_exceptions.\n  std::exception_ptr exception_;\n};\n\ntemplate <typename Result>\nclass FutureBase;\n\ntemplate <typename Result>\nclass FutureImplBase : private FutureImplResultMember<Result>, public OnceCallable {\n public:\n  enum Status { kNotStarted, kRunning, kReady };\n\n  using FutureImplResultMember<Result>::result;\n  using FutureImplResultMember<Result>::setAsResult;\n  using FutureImplResultMember<Result>::runToResult;\n\n  bool ready() {\n    return status_.intrusiveStatus().load(std::memory_order_acquire) == kReady;\n  }\n\n  void run() override {\n    (void)run(kNotStarted);\n    decRefCountMaybeDestroy();\n  }\n\n  void wait() {\n    if (waitCommon(true)) {\n      return;\n    }\n    status_.wait(kReady);\n  }\n\n  template <class Rep, class Period>\n  std::future_status waitFor(const std::chrono::duration<Rep, Period>& timeoutDuration) {\n    if (waitCommon(allowInline_) || status_.waitFor(kReady, timeoutDuration)) {\n      return std::future_status::ready;\n    }\n    return std::future_status::timeout;\n  }\n\n  template <class Clock, class Duration>\n  std::future_status waitUntil(const std::chrono::time_point<Clock, Duration>& timeoutTime) {\n    if (waitCommon(allowInline_) || status_.waitUntil(kReady, timeoutTime)) {\n      return std::future_status::ready;\n    }\n    return std::future_status::timeout;\n  }\n\n  void incRefCount() {\n    refCount_.fetch_add(1, std::memory_order_acquire);\n  }\n\n  void decRefCountMaybeDestroy() {\n    DISPENSO_TSAN_ANNOTATE_HAPPENS_BEFORE(&refCount_);\n    if (refCount_.fetch_sub(1, std::memory_order_release) == 1) {\n      DISPENSO_TSAN_ANNOTATE_HAPPENS_AFTER(&refCount_);\n      dealloc();\n    }\n  }\n\n  void setReady() {\n    status_.intrusiveStatus().store(kReady, std::memory_order_release);\n    refCount_.store(1, std::memory_order_release);\n  }\n\n  void setAllowInline(bool allow) {\n    allowInline_ = allow;\n  }\n\n  void setTaskSetCounter(std::atomic<ssize_t>* tsc) {\n    taskSetCounter_ = tsc;\n  }\n\n protected:\n  bool run(int s) {\n    while (s == kNotStarted) {\n      if (status_.intrusiveStatus().compare_exchange_weak(s, kRunning, std::memory_order_acq_rel)) {\n        runFunc();\n        status_.notify(kReady);\n        if (taskSetCounter_) {\n          //  If we want TaskSet::wait to imply Future::is_ready(),\n          //  we need to signal that *after* setting the Future status to ready.\n          taskSetCounter_->fetch_sub(1, std::memory_order_release);\n        }\n        tryExecuteThenChain();\n        return true;\n      }\n    }\n    return false;\n  }\n\n  using ThenChainInvoke = void(void*, void*);\n\n  struct ThenChain {\n    ThenChain* next;\n    void* impl;\n    void* schedulable;\n    ThenChainInvoke* invoke;\n\n    ThenChain* scheduleDestroyAndGetNext() {\n      invoke(impl, schedulable);\n      constexpr size_t kImplSize = static_cast<size_t>(nextPow2(sizeof(this)));\n      auto* ret = this->next;\n      deallocSmallBuffer<kImplSize>(this);\n      return ret;\n    }\n  };\n\n  void tryExecuteThenChain() {\n    ThenChain* head = thenChain_.load(std::memory_order_acquire);\n    // While the chain contains anything, let's try to get it and dispatch the chain.\n    while (head) {\n      if (thenChain_.compare_exchange_weak(head, nullptr, std::memory_order_acq_rel)) {\n        // Managed to exchange with head, value of thenChain_ now points to null chain.\n        // Head points to the implicit list of items to be executed.\n        while (head) {\n          head = head->scheduleDestroyAndGetNext();\n        }\n        // At this point, the list is exhausted, so we exit the outer loop too.  It would be valid\n        // to get head again and try all over again, but it is guaranteed that if another link was\n        // added concurrently to our dispatch, that thread will attempt to dispatch it's own chain,\n        // so we just exit the loop instead.\n      }\n    }\n  }\n\n  template <typename SomeFutureImpl, typename Schedulable>\n  static void thenChainInvokeAsync(void* implv, void* schedulablev) {\n    SomeFutureImpl* impl = reinterpret_cast<SomeFutureImpl*>(implv);\n    Schedulable* schedulable = reinterpret_cast<Schedulable*>(schedulablev);\n    schedulable->schedule(OnceFunction(impl, true), ForceQueuingTag());\n  }\n\n  template <typename SomeFutureImpl, typename Schedulable>\n  static void thenChainInvoke(void* implv, void* schedulablev) {\n    SomeFutureImpl* impl = reinterpret_cast<SomeFutureImpl*>(implv);\n    Schedulable* schedulable = reinterpret_cast<Schedulable*>(schedulablev);\n    schedulable->schedule(OnceFunction(impl, true));\n  }\n\n  template <typename SomeFutureImpl, typename Schedulable>\n  void addToThenChainOrExecute(SomeFutureImpl* impl, Schedulable& sched, std::launch asyncPolicy) {\n    if (status_.intrusiveStatus().load(std::memory_order_acquire) == kReady) {\n      if ((asyncPolicy & std::launch::async) == std::launch::async) {\n        sched.schedule(OnceFunction(impl, true), ForceQueuingTag());\n      } else {\n        sched.schedule(OnceFunction(impl, true));\n      }\n      return;\n    }\n\n    constexpr size_t kImplSize = static_cast<size_t>(nextPow2(sizeof(ThenChain)));\n    auto* buffer = allocSmallBuffer<kImplSize>();\n    ThenChain* link = reinterpret_cast<ThenChain*>(buffer);\n    link->impl = impl;\n    using NonConstSchedulable = std::remove_const_t<Schedulable>;\n    NonConstSchedulable* nonConstSched = const_cast<NonConstSchedulable*>(&sched);\n    link->schedulable = nonConstSched;\n    if ((asyncPolicy & std::launch::async) == std::launch::async) {\n      link->invoke = thenChainInvokeAsync<SomeFutureImpl, Schedulable>;\n    } else {\n      link->invoke = thenChainInvoke<SomeFutureImpl, Schedulable>;\n    }\n    link->next = thenChain_.load(std::memory_order_acquire);\n    while (!thenChain_.compare_exchange_weak(link->next, link, std::memory_order_acq_rel)) {\n    }\n\n    // Okay, one last thing.  It is possible that we added to the thenChain just after\n    // tryExecuteThenChain was called from run(). We still need to ensure that this work is kicked\n    // off, so just double check here, and execute if that may have happened.\n    if (status_.intrusiveStatus().load(std::memory_order_acquire) == kReady) {\n      tryExecuteThenChain();\n    }\n  }\n\n  inline bool waitCommon(bool allowInline) {\n    int s = status_.intrusiveStatus().load(std::memory_order_acquire);\n    return s == kReady || (allowInline && run(s));\n  }\n\n  virtual void runFunc() = 0;\n\n  virtual void dealloc() = 0;\n\n  // Futures always run to completion (no cancellation), so destroyOnly() is unreachable.\n  void destroyOnly() override {\n    assert(false && \"destroyOnly() should never be called on a FutureImpl\");\n  }\n\n  ~FutureImplBase() override = default;\n\n  bool allowInline_;\n\n  CompletionEventImpl status_{kNotStarted};\n  std::atomic<uint32_t> refCount_{2};\n  std::atomic<ssize_t>* taskSetCounter_{nullptr};\n\n  std::atomic<ThenChain*> thenChain_{nullptr};\n\n  template <typename R, typename T>\n  friend FutureImplBase<R&>* createValueFutureImplReady(std::reference_wrapper<T> t);\n  template <typename R, typename T>\n  friend FutureImplBase<R>* createRefFutureImplReady(T&& t);\n\n  template <typename R>\n  friend class FutureBase;\n}; // namespace detail\n\ntemplate <size_t kBufferSize, typename F, typename Result>\nclass FutureImplSmall : public FutureImplBase<Result> {\n public:\n  FutureImplSmall(F&& f) {\n    new (func_) F(std::move(f));\n  }\n\n protected:\n  void runFunc() override {\n    F* f = reinterpret_cast<F*>(func_);\n    this->runToResult(*f);\n    f->~F();\n  }\n  void dealloc() override {\n    this->~FutureImplSmall();\n    deallocSmallBuffer<kBufferSize>(this);\n  }\n\n  ~FutureImplSmall() override {}\n\n private:\n  alignas(F) char func_[sizeof(F)];\n};\n\ntemplate <size_t kBufferSize, typename Result>\nclass FutureImplSmall<kBufferSize, void, Result> : public FutureImplBase<Result> {\n protected:\n  void runFunc() override {}\n  void dealloc() override {\n    this->~FutureImplSmall();\n    deallocSmallBuffer<kBufferSize>(this);\n  }\n\n  ~FutureImplSmall() override {}\n};\n\ntemplate <typename F, typename Result>\nclass FutureImplAlloc : public FutureImplBase<Result> {\n public:\n  FutureImplAlloc(F&& f) {\n    new (func_) F(std::move(f));\n  }\n\n protected:\n  void runFunc() override {\n    F* f = reinterpret_cast<F*>(func_);\n    this->runToResult(*f);\n    f->~F();\n  }\n  void dealloc() override {\n    this->~FutureImplAlloc();\n    alignedFree(this);\n  }\n\n  ~FutureImplAlloc() override {}\n\n private:\n  alignas(F) char func_[sizeof(F)];\n};\n\ntemplate <typename Result, typename F>\ninline FutureImplBase<Result>*\ncreateFutureImpl(F&& f, bool allowInline, std::atomic<ssize_t>* taskSetCounter) {\n  using FNoRef = typename std::remove_reference<F>::type;\n  constexpr size_t kImplSize =\n      static_cast<size_t>(nextPow2(sizeof(FutureImplSmall<16, FNoRef, Result>)));\n  using SmallT = FutureImplSmall<kImplSize, FNoRef, Result>;\n\n  FutureImplBase<Result>* ret = new (allocSmallBuffer<kImplSize>()) SmallT(std::forward<F>(f));\n\n  ret->setAllowInline(allowInline);\n  ret->setTaskSetCounter(taskSetCounter);\n  return ret;\n}\n\ntemplate <typename Result, typename T>\ninline FutureImplBase<Result>* createValueFutureImplReady(T&& t) {\n  constexpr size_t kImplSize =\n      static_cast<size_t>(nextPow2(sizeof(FutureImplSmall<16, void, Result>)));\n  using SmallT = FutureImplSmall<kImplSize, void, Result>;\n\n  FutureImplBase<Result>* ret = new (allocSmallBuffer<kImplSize>()) SmallT();\n\n  ret->setAsResult(std::forward<T>(t));\n  ret->setReady();\n  return ret;\n}\n\ntemplate <typename X>\ninline FutureImplBase<X&>* createRefFutureImplReady(std::reference_wrapper<X> x) {\n  constexpr size_t kImplSize = static_cast<size_t>(nextPow2(sizeof(FutureImplSmall<16, void, X&>)));\n  using SmallT = FutureImplSmall<kImplSize, void, X&>;\n  FutureImplBase<X&>* ret = new (allocSmallBuffer<kImplSize>()) SmallT();\n  ret->setAsResult(&x.get());\n  ret->setReady();\n  return ret;\n}\n\ninline FutureImplBase<void>* createVoidFutureImplReady() {\n  constexpr size_t kImplSize =\n      static_cast<size_t>(nextPow2(sizeof(FutureImplSmall<16, void, void>)));\n  using SmallT = FutureImplSmall<kImplSize, void, void>;\n  FutureImplBase<void>* ret = new (allocSmallBuffer<kImplSize>()) SmallT();\n  ret->setReady();\n  return ret;\n}\n\ntemplate <typename TaskSetType>\nstruct TaskSetInterceptionInvoker {\n  TaskSetInterceptionInvoker(TaskSetType& ts) : taskSet(ts) {}\n\n  void schedule(OnceFunction f) {\n    savedOffFn = std::move(f);\n  }\n  void schedule(OnceFunction f, ForceQueuingTag) {\n    savedOffFn = std::move(f);\n  }\n  TaskSetType& taskSet;\n  OnceFunction savedOffFn;\n};\n\ntemplate <typename Result>\nclass FutureBase {\n protected:\n  FutureBase() noexcept : impl_(nullptr) {}\n  FutureBase(FutureBase&& f) noexcept : impl_(f.impl_) {\n    f.impl_ = nullptr;\n  }\n  FutureBase(const FutureBase& f) noexcept {\n    impl_ = f.impl_;\n    if (impl_) {\n      impl_->incRefCount();\n    }\n  }\n  template <typename F, typename Schedulable>\n  FutureBase(F&& f, Schedulable& schedulable, std::launch asyncPolicy, std::launch deferredPolicy)\n      : impl_(\n            createFutureImpl<Result>(\n                std::forward<F>(f),\n                (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n                nullptr)) {\n    if ((asyncPolicy & std::launch::async) == std::launch::async) {\n      schedulable.schedule(OnceFunction(impl_, true), ForceQueuingTag());\n    } else {\n      schedulable.schedule(OnceFunction(impl_, true));\n    }\n  }\n\n  template <typename F>\n  FutureBase(F&& f, TaskSet& taskSet, std::launch asyncPolicy, std::launch deferredPolicy)\n      : impl_(\n            createFutureImpl<Result>(\n                std::forward<F>(f),\n                (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n                &taskSet.outstandingTaskCount_)) {\n    taskSet.outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n    if ((asyncPolicy & std::launch::async) == std::launch::async) {\n      taskSet.pool().schedule(OnceFunction(impl_, true), ForceQueuingTag());\n    } else {\n      taskSet.pool().schedule(OnceFunction(impl_, true));\n    }\n  }\n\n  template <typename F>\n  FutureBase(F&& f, ConcurrentTaskSet& taskSet, std::launch asyncPolicy, std::launch deferredPolicy)\n      : impl_(\n            createFutureImpl<Result>(\n                std::forward<F>(f),\n                (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n                &taskSet.outstandingTaskCount_)) {\n    taskSet.outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n    if ((asyncPolicy & std::launch::async) == std::launch::async) {\n      taskSet.pool().schedule(OnceFunction(impl_, true), ForceQueuingTag());\n    } else {\n      taskSet.pool().schedule(OnceFunction(impl_, true));\n    }\n  }\n\n  template <typename F, typename TaskSetType>\n  FutureBase(\n      F&& f,\n      TaskSetInterceptionInvoker<TaskSetType>& invoker,\n      std::launch asyncPolicy,\n      std::launch deferredPolicy)\n      : impl_(\n            createFutureImpl<Result>(\n                std::forward<F>(f),\n                (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n                &invoker.taskSet.outstandingTaskCount_)) {\n    invoker.taskSet.outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n    if ((asyncPolicy & std::launch::async) == std::launch::async) {\n      invoker.schedule(OnceFunction(impl_, true), ForceQueuingTag());\n    } else {\n      invoker.schedule(OnceFunction(impl_, true));\n    }\n  }\n\n  void move(FutureBase&& f) noexcept {\n    if (impl_ == f.impl_) {\n      return;\n    } else if (impl_) {\n      impl_->decRefCountMaybeDestroy();\n    }\n    impl_ = f.impl_;\n    f.impl_ = nullptr;\n  }\n  void copy(const FutureBase& f) {\n    if (impl_ != f.impl_) {\n      if (impl_ != nullptr) {\n        impl_->decRefCountMaybeDestroy();\n      }\n      impl_ = f.impl_;\n      if (impl_) {\n        impl_->incRefCount();\n      }\n    }\n  }\n  ~FutureBase() {\n    if (impl_) {\n      impl_->decRefCountMaybeDestroy();\n    }\n  }\n  bool valid() const noexcept {\n    return impl_;\n  }\n  bool is_ready() const {\n    assertValid();\n    return impl_->ready();\n  }\n  void wait() const {\n    assertValid();\n    impl_->wait();\n  }\n  template <class Rep, class Period>\n  std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeoutDuration) const {\n    assertValid();\n    return impl_->waitFor(timeoutDuration);\n  }\n  template <class Clock, class Duration>\n  std::future_status wait_until(const std::chrono::time_point<Clock, Duration>& timeoutTime) const {\n    assertValid();\n    return impl_->waitUntil(timeoutTime);\n  }\n\n  template <typename RetResult, typename F, typename Schedulable>\n  FutureImplBase<RetResult>*\n  thenImpl(F&& f, Schedulable& sched, std::launch asyncPolicy, std::launch deferredPolicy);\n\n  template <typename RetResult, typename F>\n  FutureImplBase<RetResult>*\n  thenImpl(F&& f, TaskSet& sched, std::launch asyncPolicy, std::launch deferredPolicy);\n  template <typename RetResult, typename F>\n  FutureImplBase<RetResult>*\n  thenImpl(F&& f, ConcurrentTaskSet& sched, std::launch asyncPolicy, std::launch deferredPolicy);\n\n#if defined DISPENSO_DEBUG\n  void assertValid() const {\n    assert(valid());\n  }\n#else\n  void assertValid() const {}\n#endif // DISPENSO_DEBUG\n\n  mutable FutureImplBase<Result>* impl_;\n};\n\nstruct ReadyTag {};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/future_impl2.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nnamespace dispenso {\nnamespace detail {\n\n// Implementation note regarding then():\n//\n// At some point we tried to add Future::then()&&.  The impetus was that we figured we could avoid\n// making an extra copy of the *this, avoiding primarily an atomic reference increment and\n// decrement.  This lead to a 15% speedup in benchmarks.  The problem was that we were retaining a\n// copy of the bare pointer impl_ in order to call addToThenChainOrExecute.  This could lead to a\n// case where our impl_ only had one reference going into addToThenChainOrExecute, and internal to\n// that, the func is scheduled, which creates a race between the execution and potential cleanup of\n// the future internals, against completion of addToThenChainOrExecute.\n//\n// In reality this leads to *requiring* a bump of the reference count prior to\n// addToThenChainOrExecute, and a decrement afterwards.  This isn't at all cheaper (in benchmarks)\n// than just making the copy.  The moral of the story?  Don't bother with Future::then()&&.\n\ntemplate <typename Result>\ntemplate <typename RetResult, typename F, typename Schedulable>\nFutureImplBase<RetResult>* FutureBase<Result>::thenImpl(\n    F&& f,\n    Schedulable& sched,\n    std::launch asyncPolicy,\n    std::launch deferredPolicy) {\n  Future<Result> copy(*this);\n  auto func = [f = std::move(f), copy = std::move(copy)]() mutable -> RetResult {\n    copy.wait();\n    return f(std::move(copy));\n  };\n\n  auto* retImpl = createFutureImpl<RetResult>(\n      std::move(func), (deferredPolicy & std::launch::deferred) == std::launch::deferred, nullptr);\n  impl_->addToThenChainOrExecute(retImpl, sched, asyncPolicy);\n  return retImpl;\n}\n\ntemplate <typename Result>\ntemplate <typename RetResult, typename F>\nFutureImplBase<RetResult>* FutureBase<Result>::thenImpl(\n    F&& f,\n    TaskSet& sched,\n    std::launch asyncPolicy,\n    std::launch deferredPolicy) {\n  Future<Result> copy(*this);\n  auto func = [f = std::move(f), copy = std::move(copy)]() mutable -> RetResult {\n    copy.wait();\n    return f(std::move(copy));\n  };\n\n  sched.outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n  auto* retImpl = createFutureImpl<RetResult>(\n      std::move(func),\n      (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n      &sched.outstandingTaskCount_);\n  impl_->addToThenChainOrExecute(retImpl, sched.pool(), asyncPolicy);\n  return retImpl;\n}\n\ntemplate <typename Result>\ntemplate <typename RetResult, typename F>\nFutureImplBase<RetResult>* FutureBase<Result>::thenImpl(\n    F&& f,\n    ConcurrentTaskSet& sched,\n    std::launch asyncPolicy,\n    std::launch deferredPolicy) {\n  Future<Result> copy(*this);\n  auto func = [f = std::move(f), copy = std::move(copy)]() mutable -> RetResult {\n    copy.wait();\n    return f(std::move(copy));\n  };\n\n  sched.outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n  auto* retImpl = createFutureImpl<RetResult>(\n      std::move(func),\n      (deferredPolicy & std::launch::deferred) == std::launch::deferred,\n      &sched.outstandingTaskCount_);\n  impl_->addToThenChainOrExecute(retImpl, sched.pool(), asyncPolicy);\n  return retImpl;\n}\n\ntemplate <size_t index, typename... Ts>\nstruct ForEachApply {\n  template <typename F>\n  void operator()(std::tuple<Ts...>& t, F f) {\n    if (f(std::get<index>(t))) {\n      ForEachApply<index - 1, Ts...>{}(t, f);\n    }\n  }\n};\n\ntemplate <typename... Ts>\nstruct ForEachApply<size_t{0}, Ts...> {\n  template <typename F>\n  void operator()(std::tuple<Ts...>& t, F f) {\n    f(std::get<0>(t));\n  }\n};\n\ntemplate <typename F, typename... Ts>\nvoid forEach(std::tuple<Ts...>& t, F f) {\n  constexpr size_t size = std::tuple_size<std::tuple<Ts...>>::value;\n  ForEachApply<size - 1, Ts...>{}(t, f);\n}\n\ntemplate <typename VecType>\nstruct WhenAllSharedVec {\n  VecType vec;\n  std::atomic<size_t> count;\n  OnceFunction f;\n\n  template <typename InputIt, typename T = typename std::iterator_traits<InputIt>::value_type>\n  WhenAllSharedVec(InputIt first, InputIt last) : vec(first, last), count(vec.size()) {}\n};\n\ntemplate <typename Tuple>\nstruct WhenAllSharedTuple {\n  Tuple tuple;\n  std::atomic<size_t> count;\n  OnceFunction f;\n  template <typename... Types>\n  WhenAllSharedTuple(Types&&... args)\n      : tuple(std::make_tuple(std::forward<Types>(args)...)),\n        count(std::tuple_size<Tuple>::value) {}\n};\n\nstruct InterceptionInvoker {\n  void schedule(OnceFunction f) {\n    savedOffFn = std::move(f);\n  }\n  void schedule(OnceFunction f, ForceQueuingTag) {\n    savedOffFn = std::move(f);\n  }\n  OnceFunction savedOffFn;\n};\n\ntemplate <typename Invoker, typename... Futures>\nauto whenAllTuple(Invoker& invoker, Futures&&... futures)\n    -> Future<std::tuple<std::decay_t<Futures>...>> {\n  using TupleType = std::tuple<std::decay_t<Futures>...>;\n  using ResultFuture = Future<TupleType>;\n\n  // TODO(bbudge): Can write something faster than make_shared using SmallBufferAllocator.\n  auto shared =\n      std::make_shared<detail::WhenAllSharedTuple<TupleType>>(std::forward<Futures>(futures)...);\n\n  auto whenComplete = [shared]() -> TupleType {\n    forEach(shared->tuple, [&shared](auto& future) {\n      if (0 == shared->count.load(std::memory_order_acquire)) {\n        return false;\n      }\n      future.wait();\n      return true;\n    });\n    return std::move(shared->tuple);\n  };\n\n  ResultFuture res(std::move(whenComplete), invoker);\n\n  shared->f = std::move(invoker.savedOffFn);\n  // Avoid sequencing issue by getting the reference prior to the std::move.\n  auto& tuple = shared->tuple;\n  forEach(tuple, [shared = std::move(shared)](auto& future) {\n    future.then(\n        [shared](auto&&) {\n          if (shared->count.fetch_sub(1, std::memory_order_release) == 1) {\n            shared->f();\n          }\n        },\n        kImmediateInvoker);\n    return true;\n  });\n\n  return res;\n}\n\ntemplate <typename Invoker, typename InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>>\nwhenAllIterators(Invoker& invoker, InputIt first, InputIt last) {\n  using VecType = std::vector<typename std::iterator_traits<InputIt>::value_type>;\n  using ResultFuture = Future<VecType>;\n\n  if (first == last) {\n    return make_ready_future(VecType());\n  }\n\n  // TODO(bbudge): Can write something faster than make_shared using SmallBufferAllocator.\n  auto shared = std::make_shared<detail::WhenAllSharedVec<VecType>>(first, last);\n\n  auto whenComplete = [shared]() -> VecType {\n    for (auto& f : shared->vec) {\n      if (0 == shared->count.load(std::memory_order_acquire)) {\n        break;\n      }\n      f.wait();\n    }\n    return std::move(shared->vec);\n  };\n\n  ResultFuture res(std::move(whenComplete), invoker);\n\n  shared->f = std::move(invoker.savedOffFn);\n  for (auto& s : shared->vec) {\n    s.then(\n        [shared](auto&&) {\n          if (shared->count.fetch_sub(1, std::memory_order_release) == 1) {\n            shared->f();\n          }\n        },\n        kImmediateInvoker);\n  }\n\n  return res;\n}\n\n} // namespace detail\n\ntemplate <typename InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>> when_all(\n    InputIt first,\n    InputIt last) {\n  detail::InterceptionInvoker interceptor;\n  return whenAllIterators(interceptor, first, last);\n}\n\ntemplate <typename InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>>\nwhen_all(TaskSet& taskSet, InputIt first, InputIt last) {\n  detail::TaskSetInterceptionInvoker<TaskSet> interceptor(taskSet);\n  return whenAllIterators(interceptor, first, last);\n}\n\ntemplate <typename InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>>\nwhen_all(ConcurrentTaskSet& taskSet, InputIt first, InputIt last) {\n  detail::TaskSetInterceptionInvoker<ConcurrentTaskSet> interceptor(taskSet);\n  return whenAllIterators(interceptor, first, last);\n}\n\ninline auto when_all() -> Future<std::tuple<>> {\n  return make_ready_future(std::tuple<>());\n}\n\ninline auto when_all(TaskSet&) -> Future<std::tuple<>> {\n  return make_ready_future(std::tuple<>());\n}\n\ninline auto when_all(ConcurrentTaskSet&) -> Future<std::tuple<>> {\n  return make_ready_future(std::tuple<>());\n}\n\ntemplate <class... Futures>\nauto when_all(Futures&&... futures) -> Future<std::tuple<std::decay_t<Futures>...>> {\n  detail::InterceptionInvoker interceptor;\n  return whenAllTuple(interceptor, std::forward<Futures>(futures)...);\n}\n\ntemplate <typename... Futures>\nauto when_all(TaskSet& taskSet, Futures&&... futures)\n    -> Future<std::tuple<std::decay_t<Futures>...>> {\n  detail::TaskSetInterceptionInvoker<TaskSet> interceptor(taskSet);\n  return whenAllTuple(interceptor, std::forward<Futures>(futures)...);\n}\n\ntemplate <typename... Futures>\nauto when_all(ConcurrentTaskSet& taskSet, Futures&&... futures)\n    -> Future<std::tuple<std::decay_t<Futures>...>> {\n  detail::TaskSetInterceptionInvoker<ConcurrentTaskSet> interceptor(taskSet);\n  return whenAllTuple(interceptor, std::forward<Futures>(futures)...);\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/graph_executor_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n#include <dispenso/graph.h>\n#include <dispenso/platform.h>\n#include <dispenso/task_set.h>\n\n#include <unordered_set>\n\nnamespace detail {\n\n// Maximum recursion depth for inline graph node scheduling before forcing work\n// through the thread pool queue. Prevents unbounded stack growth when CTS inlines\n// evaluateNodeConcurrently calls for additional ready dependents.\nstatic constexpr int kMaxGraphInlineDepth = 32;\n\nclass ExecutorBase {\n protected:\n  inline static bool hasNoIncompletePredecessors(const dispenso::Node& node) {\n    return node.numIncompletePredecessors_.load(std::memory_order_relaxed) == 0;\n  }\n\n  inline static void addIncompletePredecessor(const dispenso::Node& node) {\n    if (node.isCompleted()) {\n      node.numIncompletePredecessors_.store(1, std::memory_order_relaxed);\n    } else {\n      node.numIncompletePredecessors_.fetch_add(1, std::memory_order_relaxed);\n    }\n  }\n\n  inline static void ifIncompleteAddIncompletePredecessor(const dispenso::Node& node) {\n    if (!node.isCompleted()) {\n      node.numIncompletePredecessors_.fetch_add(1, std::memory_order_relaxed);\n    }\n  }\n\n  inline static bool decNumIncompletePredecessors(\n      const dispenso::Node& node,\n      std::memory_order order) {\n    return node.numIncompletePredecessors_.fetch_sub(1, order) == 1;\n  }\n\n  inline static bool decNumIncompletePredecessors(\n      const dispenso::BiPropNode& node,\n      std::memory_order order) {\n    const std::memory_order loadOrder =\n        order == std::memory_order_relaxed ? std::memory_order_relaxed : std::memory_order_acquire;\n    if (node.numIncompletePredecessors_.load(loadOrder) == dispenso::Node::kCompleted) {\n      return false;\n    }\n\n    return node.numIncompletePredecessors_.fetch_sub(1, order) == 1;\n  }\n\n  template <class N>\n  inline static void evaluateNodeConcurrently(dispenso::ConcurrentTaskSet& tasks, const N* node) {\n    // Track recursion depth to prevent stack overflow. CTS may inline scheduled\n    // lambdas when load is high, causing evaluateNodeConcurrently to recurse\n    // through the schedule→inline→evaluate path. When depth exceeds the limit,\n    // force work through the pool queue to bound stack growth.\n    static DISPENSO_THREAD_LOCAL int depth = 0;\n    struct DepthGuard {\n      DISPENSO_INLINE DepthGuard(int& d) : d_(d) {\n        ++d_;\n      }\n      DISPENSO_INLINE ~DepthGuard() {\n        --d_;\n      }\n      int& d_;\n    };\n    DepthGuard dGuard(depth);\n\n    // Process nodes in a loop, continuing inline with first ready dependent\n    // to avoid task scheduling overhead on the critical path\n    while (node != nullptr) {\n      node->run();\n\n      const N* inlineNext = nullptr;\n      for (const dispenso::Node* const d : node->dependents_) {\n        if (decNumIncompletePredecessors(static_cast<const N&>(*d), std::memory_order_acq_rel)) {\n          const N* dep = static_cast<const N*>(d);\n          if (inlineNext == nullptr) {\n            // First ready dependent: continue with it inline\n            inlineNext = dep;\n          } else if (depth < kMaxGraphInlineDepth) {\n            // Additional ready dependents: schedule to task queue\n            tasks.schedule([&tasks, dep]() { evaluateNodeConcurrently(tasks, dep); });\n          } else {\n            // Depth limit reached: force enqueue to prevent stack overflow\n            tasks.schedule(\n                [&tasks, dep]() { evaluateNodeConcurrently(tasks, dep); },\n                dispenso::ForceQueuingTag());\n          }\n        }\n      }\n      node = inlineNext;\n    }\n  }\n\n  static void appendGroup(\n      const dispenso::Node* /* node */,\n      std::unordered_set<const std::vector<const dispenso::BiPropNode*>*>& /* groups */) {}\n\n  static void appendGroup(\n      const dispenso::BiPropNode* node,\n      std::unordered_set<const std::vector<const dispenso::BiPropNode*>*>& groups) {\n    const std::vector<const dispenso::BiPropNode*>* group = node->biPropSet_.get();\n    if (group != nullptr) {\n      groups.insert(group);\n    }\n  }\n};\n\n} // namespace detail\n"
  },
  {
    "path": "dispenso/detail/math.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <stdint.h>\n#include <type_traits>\n\n#if defined(_WIN32)\n#include <intrin.h>\n#endif //_WIN32\n\nnamespace dispenso {\n\nnamespace detail {\n\nconstexpr uint64_t nextPow2(uint64_t v) {\n  // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2\n  v--;\n  v |= v >> 1;\n  v |= v >> 2;\n  v |= v >> 4;\n  v |= v >> 8;\n  v |= v >> 16;\n  v |= v >> 32;\n  v++;\n  return v;\n}\n\nconstexpr inline uint32_t log2const(uint64_t v) {\n  constexpr uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000UL};\n  constexpr uint32_t S[] = {1, 2, 4, 8, 16, 32};\n\n  uint32_t r = 0;\n  for (uint32_t i = 6; i--;) {\n    if (v & b[i]) {\n      v >>= S[i];\n      r |= S[i];\n    }\n  }\n\n  return r;\n}\n\nconstexpr inline uint32_t log2const(uint32_t v) {\n  constexpr uint32_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};\n  constexpr uint32_t S[] = {1, 2, 4, 8, 16};\n\n  uint32_t r = 0;\n  for (uint32_t i = 5; i--;) {\n    if (v & b[i]) {\n      v >>= S[i];\n      r |= S[i];\n    }\n  }\n\n  return r;\n}\n\n// On some platforms (e.g. macOS ARM64), size_t is 'unsigned long' which is a distinct type\n// from both uint32_t and uint64_t, causing overload ambiguity. This template resolves it\n// by delegating to the 64-bit overload; it is SFINAE-disabled on platforms where unsigned\n// long already matches one of the fixed-width types (Linux, Windows), so no behavior change.\ntemplate <\n    typename T = unsigned long,\n    typename std::enable_if<\n        !std::is_same<T, uint32_t>::value && !std::is_same<T, uint64_t>::value,\n        int>::type = 0>\nconstexpr inline uint32_t log2const(T v) {\n  return log2const(static_cast<uint64_t>(v));\n}\n\n// --- 64-bit log2 ---\n\n#if (defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__)\ninline uint32_t log2(uint64_t v) {\n  uint64_t result;\n  __asm__(\"bsrq %1, %0\" : \"=r\"(result) : \"r\"(v));\n  return static_cast<uint32_t>(result);\n}\n#elif (defined(__GNUC__) || defined(__clang__))\ninline uint32_t log2(uint64_t v) {\n  return static_cast<uint32_t>(63 - __builtin_clzll(v));\n}\n#elif defined(_WIN64)\ninline uint32_t log2(uint64_t v) {\n  unsigned long index;\n  _BitScanReverse64(&index, v);\n  return static_cast<uint32_t>(index);\n}\n#elif defined(_WIN32)\ninline uint32_t log2(uint64_t v) {\n  unsigned long index;\n  uint32_t hi = static_cast<uint32_t>(v >> 32);\n  if (hi != 0) {\n    _BitScanReverse(&index, hi);\n    return static_cast<uint32_t>(index + 32);\n  }\n  _BitScanReverse(&index, static_cast<uint32_t>(v));\n  return static_cast<uint32_t>(index);\n}\n#else\ninline uint32_t log2(uint64_t v) {\n  return log2const(v);\n}\n#endif // 64-bit\n\ntemplate <\n    typename T = unsigned long,\n    typename std::enable_if<\n        !std::is_same<T, uint32_t>::value && !std::is_same<T, uint64_t>::value,\n        int>::type = 0>\ninline uint32_t log2(T v) {\n  return log2(static_cast<uint64_t>(v));\n}\n\n// --- 32-bit log2 ---\n\n#if (defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(__i386__))\ninline uint32_t log2(uint32_t v) {\n  uint32_t result;\n  __asm__(\"bsrl %1, %0\" : \"=r\"(result) : \"r\"(v));\n  return result;\n}\n#elif (defined(__GNUC__) || defined(__clang__))\ninline uint32_t log2(uint32_t v) {\n  return static_cast<uint32_t>(31 - __builtin_clz(v));\n}\n#elif defined(_WIN32)\ninline uint32_t log2(uint32_t v) {\n  unsigned long index;\n  _BitScanReverse(&index, v);\n  return static_cast<uint32_t>(index);\n}\n#else\ninline uint32_t log2(uint32_t v) {\n  return log2const(v);\n}\n#endif // 32-bit\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/notifier_common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n// For fallback path\n#include <condition_variable>\n#include <mutex>\n\n#if defined(__linux__)\n#include <errno.h>\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\nnamespace dispenso {\nnamespace detail {\nstatic int futex(\n    int* uaddr,\n    int futex_op,\n    int val,\n    const struct timespec* timeout,\n    int* /*uaddr2*/,\n    int val3) {\n  return static_cast<int>(syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr, val3));\n}\n} // namespace detail\n} // namespace dispenso\n\n#elif defined(__MACH__)\n#include <Availability.h>\n#include <errno.h>\n#include <mach/mach_time.h>\n\n// Detect os_sync_wait_on_address availability (macOS 14.4+)\n#if defined(__has_include)\n#if __has_include(<os/os_sync_wait_on_address.h>)\n#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140400\n#define DISPENSO_HAS_OS_SYNC 1\n#include <os/os_sync_wait_on_address.h>\n#endif\n#endif\n#endif\n\n#ifndef DISPENSO_HAS_OS_SYNC\n// __ulock APIs are available since macOS 10.12 (Sierra). On older versions (e.g. PPC/10.5 builds\n// for MacPorts), fall through to the std::mutex fallback.\n#if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200\n#define DISPENSO_HAS_ULOCK 1\nextern \"C\" int __ulock_wait(uint32_t operation, void* addr, uint64_t value, uint32_t timeout_us);\nextern \"C\" int __ulock_wake(uint32_t operation, void* addr, uint64_t value);\n\n#ifndef UL_COMPARE_AND_WAIT\n#define UL_COMPARE_AND_WAIT 1\n#endif\n#ifndef ULF_WAKE_ALL\n#define ULF_WAKE_ALL 0x00000100\n#endif\n#endif // macOS >= 10.12\n#endif // DISPENSO_HAS_OS_SYNC\n\n// DISPENSO_HAS_MAC_FUTEX is set when any mac futex-like API is available.\n#if defined(DISPENSO_HAS_OS_SYNC) || defined(DISPENSO_HAS_ULOCK)\n#define DISPENSO_HAS_MAC_FUTEX 1\n#endif\n\n#ifdef DISPENSO_HAS_MAC_FUTEX\nnamespace dispenso {\nnamespace detail {\n\ninline void mac_futex_wait(void* addr, uint64_t expected, size_t size) {\n#ifdef DISPENSO_HAS_OS_SYNC\n  os_sync_wait_on_address(addr, expected, size, OS_SYNC_WAIT_ON_ADDRESS_NONE);\n#else\n  (void)size;\n  __ulock_wait(UL_COMPARE_AND_WAIT, addr, expected, 0);\n#endif\n}\n\ninline int mac_futex_wait_for(void* addr, uint64_t expected, size_t size, uint64_t relTimeUs) {\n#ifdef DISPENSO_HAS_OS_SYNC\n  static mach_timebase_info_data_t sTimebaseInfo = []() {\n    mach_timebase_info_data_t i;\n    mach_timebase_info(&i);\n    return i;\n  }();\n  uint64_t ns = relTimeUs * 1000;\n  uint64_t timeout = ns * sTimebaseInfo.denom / sTimebaseInfo.numer;\n  return os_sync_wait_on_address_with_timeout(\n      addr, expected, size, OS_SYNC_WAIT_ON_ADDRESS_NONE, OS_CLOCK_MACH_ABSOLUTE_TIME, timeout);\n#else\n  (void)size;\n  // __ulock_wait takes a uint32_t timeout in microseconds, which wraps at ~4295 seconds (~72 min).\n  // Timeouts beyond that cause a spurious early wake, which is harmless since callers re-check\n  // status in a loop.\n  return __ulock_wait(UL_COMPARE_AND_WAIT, addr, expected, static_cast<uint32_t>(relTimeUs));\n#endif\n}\n\ninline void mac_futex_wake_one(void* addr, size_t size) {\n#ifdef DISPENSO_HAS_OS_SYNC\n  os_sync_wake_by_address_any(addr, size, OS_SYNC_WAKE_BY_ADDRESS_NONE);\n#else\n  (void)size;\n  __ulock_wake(UL_COMPARE_AND_WAIT, addr, 0);\n#endif\n}\n\ninline void mac_futex_wake_all(void* addr, size_t size) {\n#ifdef DISPENSO_HAS_OS_SYNC\n  os_sync_wake_by_address_all(addr, size, OS_SYNC_WAKE_BY_ADDRESS_NONE);\n#else\n  (void)size;\n  __ulock_wake(UL_COMPARE_AND_WAIT | ULF_WAKE_ALL, addr, 0);\n#endif\n}\n\n} // namespace detail\n} // namespace dispenso\n#endif // DISPENSO_HAS_MAC_FUTEX\n\n#elif defined(_WIN32)\n\n#if (defined(_M_ARM64) || defined(__aarch64__)) && !defined(_ARM64_)\n#define _ARM64_\n#elif (defined(_M_ARM) || defined(__arm__)) && !defined(_ARM_)\n#define _ARM_\n#elif (defined(_M_AMD64) || defined(__x86_64__) || defined(_WIN64)) && !defined(_AMD64_)\n#define _AMD64_\n#elif !defined(_X86_)\n#define _X86_\n#endif // platform\n\n#include <errhandlingapi.h>\n#include <synchapi.h>\n\nnamespace dispenso {\nnamespace detail {\n\nconstexpr int kErrorTimeoutWin = 0x000005B4;\nconstexpr unsigned long kInfiniteWin = static_cast<unsigned long>(-1);\n\n} // namespace detail\n} // namespace dispenso\n\n#endif // PLATFORM\n"
  },
  {
    "path": "dispenso/detail/once_callable_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/detail/math.h>\n#include <dispenso/platform.h>\n#include <dispenso/small_buffer_allocator.h>\n\nnamespace dispenso {\nnamespace detail {\n\nclass OnceCallable {\n public:\n  virtual void run() = 0;\n  virtual void destroyOnly() = 0;\n  virtual ~OnceCallable() = default;\n};\n\nstruct OnceCallableData {\n  void* data;\n  void (*invoke)(void*, bool run);\n};\n\ntemplate <size_t kBufferSize, typename F>\nvoid invokeImpl(void* ptr, bool run) {\n  F* f = static_cast<F*>(ptr);\n  if (DISPENSO_EXPECT(run, true)) {\n    (*f)();\n  }\n  f->~F();\n  deallocSmallBuffer<kBufferSize>(ptr);\n}\n\ntemplate <typename F>\ninline OnceCallableData createOnceCallable(F&& f) {\n  using FNoRef = typename std::remove_reference<F>::type;\n\n  constexpr size_t kAllocSize =\n      static_cast<size_t>(nextPow2(std::max(sizeof(FNoRef), alignof(FNoRef))));\n\n  void* buf = allocSmallBuffer<kAllocSize>();\n  new (buf) FNoRef(std::forward<F>(f));\n  return {buf, &invokeImpl<kAllocSize, FNoRef>};\n}\n\ninline void runOnceCallable(void* ptr, bool run) {\n  auto* callable = static_cast<OnceCallable*>(ptr);\n  if (DISPENSO_EXPECT(run, true)) {\n    callable->run();\n  } else {\n    callable->destroyOnly();\n  }\n}\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/op_result.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <type_traits>\n#include <utility>\n\nnamespace dispenso {\nnamespace detail {\n\ntemplate <typename T>\nclass OpResult {\n public:\n  OpResult() : ptr_(nullptr) {}\n\n  template <\n      typename U,\n      typename = typename std::enable_if<\n          !std::is_same<typename std::decay<U>::type, OpResult<T>>::value>::type>\n  OpResult(U&& u) : ptr_(new (buf_) T(std::forward<U>(u))) {}\n\n  OpResult(const OpResult<T>& oth) : ptr_(oth ? new (buf_) T(*oth.ptr_) : nullptr) {}\n\n  OpResult(OpResult<T>&& oth) : ptr_(oth ? new (buf_) T(std::move(*oth.ptr_)) : nullptr) {\n    oth.ptr_ = nullptr;\n  }\n\n  OpResult& operator=(const OpResult& oth) {\n    if (&oth == this) {\n      return *this;\n    }\n    if (ptr_) {\n      ptr_->~T();\n    }\n\n    if (oth) {\n      ptr_ = new (buf_) T(*oth.ptr_);\n    } else {\n      ptr_ = nullptr;\n    }\n    return *this;\n  }\n\n  OpResult& operator=(OpResult&& oth) {\n    if (&oth == this) {\n      return *this;\n    }\n    if (ptr_) {\n      ptr_->~T();\n    }\n\n    if (oth) {\n      ptr_ = new (buf_) T(std::move(*oth.ptr_));\n      oth.ptr_ = nullptr;\n    } else {\n      ptr_ = nullptr;\n    }\n\n    return *this;\n  }\n\n  ~OpResult() {\n    if (ptr_) {\n      ptr_->~T();\n    }\n  }\n\n  template <typename... Args>\n  T& emplace(Args&&... args) {\n    if (ptr_) {\n      ptr_->~T();\n    }\n    ptr_ = new (buf_) T(std::forward<Args>(args)...);\n    return *ptr_;\n  }\n\n  operator bool() const {\n    return ptr_;\n  }\n\n  bool has_value() const {\n    return ptr_;\n  }\n\n  T& value() {\n    return *ptr_;\n  }\n\n private:\n  alignas(T) char buf_[sizeof(T)];\n  T* ptr_;\n};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/per_thread_info.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/detail/per_thread_info.h>\n\nnamespace dispenso {\nnamespace detail {\n\nnamespace {\nDISPENSO_THREAD_LOCAL PerThreadInfo g_perThreadInfo;\n}\nPerThreadInfo& PerPoolPerThreadInfo::info() {\n  return g_perThreadInfo;\n}\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/per_thread_info.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\nnamespace detail {\n\nstruct alignas(kCacheLineSize) PerThreadInfo {\n  void* pool = nullptr;\n  void* producer = nullptr;\n  int parForRecursionLevel = 0;\n};\n\nclass ParForRecursion {\n public:\n  ~ParForRecursion() {\n    --parForRecursionLevel_;\n  }\n\n private:\n  ParForRecursion(int& parForRecursionLevel) : parForRecursionLevel_(parForRecursionLevel) {\n    ++parForRecursionLevel_;\n  }\n\n  int& parForRecursionLevel_;\n  friend class PerPoolPerThreadInfo;\n};\n\nclass PerPoolPerThreadInfo {\n public:\n  static void registerPool(void* pool, void* producer) {\n    auto& i = info();\n    i.pool = pool;\n    i.producer = producer;\n  }\n\n  static void* producer(void* pool) {\n    auto& i = info();\n    return i.pool == pool ? i.producer : nullptr;\n  }\n\n  static bool isParForRecursive(void* pool) {\n    auto& i = info();\n    return (!i.pool || i.pool == pool) && i.parForRecursionLevel > 0;\n  }\n\n  static bool isPoolRecursive(void* pool) {\n    return info().pool == pool;\n  }\n\n  static ParForRecursion parForRecurse() {\n    return ParForRecursion(info().parForRecursionLevel);\n  }\n\n private:\n  DISPENSO_DLL_ACCESS static PerThreadInfo& info();\n};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/pipeline_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#if __cplusplus >= 201703L\n#include <optional>\n#endif // C++17\n\n#include <dispenso/detail/completion_event_impl.h>\n#include <dispenso/detail/op_result.h>\n#include <dispenso/detail/result_of.h>\n#include <dispenso/task_set.h>\n#include <dispenso/tsan_annotations.h>\n\nnamespace dispenso {\nnamespace detail {\n\n// Maximum depth for inline pipeline continuation before forcing a schedule through\n// the thread pool. Prevents unbounded stack growth when the pool inlines execution.\nstatic constexpr int kMaxPipelineInlineDepth = 32;\n\nclass LimitGatedScheduler {\n public:\n  LimitGatedScheduler(ConcurrentTaskSet& tasks, ssize_t res)\n      : impl_(new (alignedMalloc(sizeof(Impl), alignof(Impl))) Impl(tasks, res)) {}\n\n  template <typename F>\n  void schedule(F&& fPipe) {\n    impl_->schedule(std::forward<F>(fPipe));\n  }\n\n  void wait() {\n    impl_->wait();\n  }\n\n private:\n  // Put the guts within a unique_ptr to enable this type to be movable.\n  class Impl {\n   public:\n    Impl(ConcurrentTaskSet& tasks, ssize_t res)\n        : tasks_(tasks),\n          resources_(res),\n          unlimited_(res == std::numeric_limits<ssize_t>::max()),\n          serial_(res == 1) {}\n\n    template <typename F>\n    void schedule(F&& fPipe) {\n      outstanding_.fetch_add(1, std::memory_order_acq_rel);\n\n      // RAII guard ensures outstanding_ is decremented even if an exception propagates.\n      // Without this, wait() would hang spinning on outstanding_ reaching zero.\n      struct OutstandingGuard {\n        DISPENSO_INLINE ~OutstandingGuard() {\n          outstanding_.fetch_sub(1, std::memory_order_acq_rel);\n        }\n        std::atomic<size_t>& outstanding_;\n      };\n\n      if (unlimited_) {\n        tasks_.schedule([this, fPipe = std::move(fPipe)]() mutable {\n          OutstandingGuard oGuard{outstanding_};\n          if (!tasks_.hasException()) {\n            fPipe([]() {});\n          }\n        });\n        return;\n      }\n\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n      queue_.enqueue([this, fPipe = std::move(fPipe)]() mutable {\n        OutstandingGuard oGuard{outstanding_};\n\n        // RAII guard releases the resource slot if the completion callback is never\n        // called (i.e. if the user's stage function throws before reaching it).\n        // Disarmed on the normal path when the completion callback fires.\n        struct ResourceGuard {\n          DISPENSO_INLINE ~ResourceGuard() {\n            if (armed_) {\n              resources_.fetch_add(1, std::memory_order_acq_rel);\n            }\n          }\n          DISPENSO_INLINE void disarm() {\n            armed_ = false;\n          }\n          std::atomic<ssize_t>& resources_;\n          bool armed_{true};\n        };\n        ResourceGuard rGuard{resources_};\n\n#if defined(__cpp_exceptions)\n        try {\n#endif\n          fPipe([this, &rGuard]() {\n            rGuard.disarm();\n            OnceFunction func;\n            DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n            bool deqd = queue_.try_dequeue(func);\n            DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n            if (deqd) {\n              // For serial stages (limit=1), execute continuation inline to reduce\n              // thread pool scheduling overhead. This is safe because we're already\n              // on a worker thread and only one item can be in the stage at a time.\n              // Depth-limit to prevent unbounded stack growth when the pool inlines.\n              if (serial_) {\n                static DISPENSO_THREAD_LOCAL int depth = 0;\n                if (depth < kMaxPipelineInlineDepth) {\n                  struct DepthGuard {\n                    DISPENSO_INLINE DepthGuard(int& d) : d_(d) {\n                      ++d_;\n                    }\n                    DISPENSO_INLINE ~DepthGuard() {\n                      --d_;\n                    }\n                    int& d_;\n                  };\n                  DepthGuard dGuard(depth);\n                  func();\n                } else {\n                  tasks_.schedule(std::move(func), ForceQueuingTag());\n                }\n              } else {\n                tasks_.schedule(std::move(func));\n              }\n            } else {\n              resources_.fetch_add(1, std::memory_order_acq_rel);\n            }\n          });\n#if defined(__cpp_exceptions)\n        } catch (...) {\n          tasks_.trySetCurrentException();\n        }\n#endif\n      });\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n\n      while (resources_.fetch_sub(1, std::memory_order_acq_rel) > 0) {\n        OnceFunction func;\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n        bool deqd = queue_.try_dequeue(func);\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n        if (deqd) {\n          tasks_.schedule(std::move(func));\n        } else {\n          break;\n        }\n      }\n      resources_.fetch_add(1, std::memory_order_acq_rel);\n    }\n\n    void wait() {\n      if (!unlimited_) {\n        // LIMITED path: drain items from the local queue into the\n        // ConcurrentTaskSet, and spin until all outstanding items for this\n        // stage have completed. We must spin on outstanding_ because in-flight\n        // CTS tasks from the previous stage may call pipeNext_.execute() after\n        // this drain starts, enqueuing new items into our local queue. Without\n        // the outstanding_ check, those late-arriving items could be orphaned\n        // if schedule()'s try_dequeue spuriously misses them.\n        while (outstanding_.load(std::memory_order_acquire)) {\n          if (tasks_.hasException()) {\n            // Drain remaining queued items without executing them.\n            OnceFunction discard;\n            while (queue_.try_dequeue(discard)) {\n              outstanding_.fetch_sub(1, std::memory_order_acq_rel);\n              discard.cleanupNotRun();\n            }\n            break;\n          }\n          OnceFunction func;\n          DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n          bool deqd = queue_.try_dequeue(func);\n          DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n          if (deqd) {\n            // Spin until a resource slot is available. Check for exceptions\n            // each iteration to avoid deadlocking when all pool threads have\n            // finished and no one will release a resource.\n            while (resources_.fetch_sub(1, std::memory_order_acq_rel) <= 0) {\n              resources_.fetch_add(1, std::memory_order_acq_rel);\n              if (tasks_.hasException()) {\n                outstanding_.fetch_sub(1, std::memory_order_acq_rel);\n                func.cleanupNotRun();\n                goto next_item;\n              }\n              if (!tasks_.tryExecuteNext()) {\n                std::this_thread::yield();\n              }\n            }\n            tasks_.schedule(std::move(func));\n          next_item:;\n          } else if (!tasks_.tryExecuteNext()) {\n            std::this_thread::yield();\n          }\n        }\n        return;\n      }\n\n      // Unified drain + wait loop. We must keep checking the local queue\n      // because items can arrive after an earlier drain pass — this happens\n      // when a completion callback's try_dequeue races with a concurrent\n      // enqueue: the callback sees an empty queue and releases the resource\n      // instead of chaining, leaving the item orphaned in the queue.\n      // Re-checking on every iteration ensures we eventually dispatch it.\n      while (outstanding_.load(std::memory_order_acquire)) {\n        // For the unlimited path, items are scheduled directly to CTS (not\n        // queued locally). When an exception occurs, remaining items are\n        // already in CTS's pool queue wrapped by packageTask — CTS::wait()\n        // will drain them. Break out here to avoid spinning.\n        if (tasks_.hasException()) {\n          break;\n        }\n        OnceFunction func;\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n        bool deqd = queue_.try_dequeue(func);\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n        if (deqd) {\n          // Wait for resource to become available\n          while (resources_.fetch_sub(1, std::memory_order_acq_rel) <= 0) {\n            resources_.fetch_add(1, std::memory_order_acq_rel);\n            if (!tasks_.tryExecuteNext()) {\n              std::this_thread::yield();\n            }\n          }\n          tasks_.schedule(std::move(func));\n        } else if (!tasks_.tryExecuteNext()) {\n          std::this_thread::yield();\n        }\n      }\n    }\n\n   private:\n    ConcurrentTaskSet& tasks_;\n    alignas(kCacheLineSize) std::atomic<ssize_t> resources_;\n    alignas(kCacheLineSize) std::atomic<size_t> outstanding_{0};\n    moodycamel::ConcurrentQueue<OnceFunction> queue_;\n    // Note: In benchmarks, this doesn't seem to help very much (~1%), but using it should lower\n    // resource requirements because the queue_ never needs to instantiate memory.\n    const bool unlimited_;\n    const bool serial_;\n  };\n\n  struct Deleter {\n    void operator()(Impl* r) {\n      r->~Impl();\n      alignedFree(r);\n    }\n  };\n\n  std::unique_ptr<Impl, Deleter> impl_;\n};\n\ntemplate <typename F>\nstruct Stage {\n  Stage(F&& fIn, ssize_t limitIn) : f(std::move(fIn)), limit(limitIn) {}\n\n  template <typename T>\n  auto operator()(T&& t) {\n    return f(std::forward<T>(t));\n  }\n\n  auto operator()() {\n    return f();\n  }\n\n  F f;\n  ssize_t limit;\n};\n\ntemplate <typename T>\nstruct StageLimits {\n  constexpr static ssize_t limit(const T& /*t*/) {\n    return 1;\n  }\n};\n\ntemplate <typename T>\nstruct StageLimits<Stage<T>> {\n  static ssize_t limit(const Stage<T>& t) {\n    return std::max(ssize_t{1}, t.limit);\n  }\n};\n\nenum class StageClass { kSingleStage, kGenerator, kOpTransform, kTransform, kSink };\n\ntemplate <typename T>\nstruct TransformTraits {\n  static constexpr StageClass kStageClass = StageClass::kTransform;\n};\n\n#if __cplusplus >= 201703L\ntemplate <typename T>\nstruct TransformTraits<std::optional<T>> {\n  static constexpr StageClass kStageClass = StageClass::kOpTransform;\n};\n#endif // C++17\n\ntemplate <typename T>\nstruct TransformTraits<OpResult<T>> {\n  static constexpr StageClass kStageClass = StageClass::kOpTransform;\n};\n\ntemplate <typename T>\nstruct OptionalStrippedTraits {\n  using Type = T;\n};\n\n#if __cplusplus >= 201703L\ntemplate <typename T>\nstruct OptionalStrippedTraits<std::optional<T>> {\n  using Type = T;\n};\n#endif // C++17\n\ntemplate <typename T>\nstruct OptionalStrippedTraits<OpResult<T>> {\n  using Type = T;\n};\n\nstruct SinkPipe {};\n\ntemplate <StageClass stageClass, typename CurStage, typename PipeNext>\nclass Pipe;\n\ntemplate <typename CurStage, typename PipeNext>\nclass TransformPipe {\n public:\n  template <typename StageIn>\n  TransformPipe(ConcurrentTaskSet& tasks, StageIn&& s, PipeNext&& n)\n      : stage_(std::forward<StageIn>(s)),\n        tasks_(tasks, StageLimits<CurStage>::limit(stage_)),\n        pipeNext_(std::move(n)) {}\n\n  void wait() {\n    tasks_.wait();\n    pipeNext_.wait();\n  }\n\n protected:\n  CurStage stage_;\n  LimitGatedScheduler tasks_;\n  PipeNext pipeNext_;\n};\n\ntemplate <typename CurStage, typename PipeNext>\nclass Pipe<StageClass::kTransform, CurStage, PipeNext> : public TransformPipe<CurStage, PipeNext> {\n public:\n  template <typename StageIn>\n  Pipe(ConcurrentTaskSet& tasks, StageIn&& s, PipeNext&& n)\n      : TransformPipe<CurStage, PipeNext>(tasks, std::forward<StageIn>(s), std::move(n)) {}\n\n  template <typename Input>\n  void execute(Input&& input) {\n    this->tasks_.schedule([input = std::move(input), this](auto&& stageCompleteFunc) mutable {\n      auto&& res = this->stage_(std::move(input));\n      stageCompleteFunc();\n      this->pipeNext_.execute(res);\n    });\n  }\n};\n\ntemplate <typename CurStage, typename PipeNext>\nclass Pipe<StageClass::kOpTransform, CurStage, PipeNext>\n    : public TransformPipe<CurStage, PipeNext> {\n public:\n  template <typename StageIn>\n  Pipe(ConcurrentTaskSet& tasks, StageIn&& s, PipeNext&& n)\n      : TransformPipe<CurStage, PipeNext>(tasks, std::forward<StageIn>(s), std::move(n)) {}\n\n  template <typename Input>\n  void execute(Input&& input) {\n    this->tasks_.schedule([input = std::move(input), this](auto&& stageCompleteFunc) mutable {\n      auto op = this->stage_(std::move(input));\n      stageCompleteFunc();\n      if (op) {\n        this->pipeNext_.execute(std::move(op.value()));\n      }\n    });\n  }\n};\n\ntemplate <typename CurStage, typename PipeNext>\nclass Pipe<StageClass::kGenerator, CurStage, PipeNext> {\n public:\n  template <typename StageIn>\n  Pipe(ConcurrentTaskSet& tasks, StageIn&& s, PipeNext&& n)\n      : tasks_(tasks), stage_(std::forward<StageIn>(s)), pipeNext_(std::move(n)) {}\n\n  void execute() {\n    ssize_t numThreads = std::max<ssize_t>(\n        1, std::min(tasks_.numPoolThreads(), StageLimits<CurStage>::limit(stage_)));\n    completion_ = std::make_unique<CompletionEventImpl>(static_cast<int>(numThreads));\n    for (ssize_t i = 0; i < numThreads; ++i) {\n      tasks_.schedule([this]() {\n        // RAII guard ensures the completion event is signaled even if an exception\n        // propagates out of pipeNext_.execute() (e.g. when ConcurrentTaskSet runs a\n        // downstream stage inline and it throws). Without this, wait() would hang on\n        // completion_->wait(0) because the count is never decremented.\n        struct CompletionGuard {\n          DISPENSO_INLINE ~CompletionGuard() {\n            if (completion->intrusiveStatus().fetch_sub(1, std::memory_order_acq_rel) == 1) {\n              completion->notify(0);\n            }\n          }\n          CompletionEventImpl* completion;\n        };\n        CompletionGuard cGuard{completion_.get()};\n\n        while (!tasks_.hasException()) {\n          auto op = stage_();\n          if (!op) {\n            break;\n          }\n          pipeNext_.execute(std::move(op.value()));\n        }\n      });\n    }\n  }\n\n  void wait() {\n    completion_->wait(0);\n    pipeNext_.wait();\n    tasks_.wait();\n  }\n\n private:\n  ConcurrentTaskSet& tasks_;\n  std::unique_ptr<CompletionEventImpl> completion_;\n  CurStage stage_;\n  PipeNext pipeNext_;\n};\n\ntemplate <typename CurStage>\nclass Pipe<StageClass::kSingleStage, CurStage, SinkPipe> {\n public:\n  template <typename StageIn>\n  Pipe(ConcurrentTaskSet& tasks, StageIn&& s) : tasks_(tasks), stage_(std::forward<StageIn>(s)) {}\n\n  void execute() {\n    size_t numThreads = std::min(tasks_.numPoolThreads(), StageLimits<CurStage>::limit(stage_));\n    for (size_t i = 0; i < numThreads; ++i) {\n      tasks_.schedule([this]() {\n        while (!tasks_.hasException() && stage_()) {\n        }\n      });\n    }\n  }\n\n  void wait() {\n    tasks_.wait();\n  }\n\n private:\n  ConcurrentTaskSet& tasks_;\n  CurStage stage_;\n};\n\ntemplate <typename CurStage>\nclass Pipe<StageClass::kSink, CurStage, SinkPipe> {\n public:\n  template <typename StageIn>\n  Pipe(ConcurrentTaskSet& tasks, StageIn&& s)\n      : stage_(std::forward<StageIn>(s)), tasks_(tasks, StageLimits<CurStage>::limit(stage_)) {}\n\n  template <typename Input>\n  void execute(Input&& input) {\n    tasks_.schedule([input = std::move(input), this](auto&& stageCompleteFunc) mutable {\n      stage_(std::move(input));\n      stageCompleteFunc();\n    });\n  }\n\n  void wait() {\n    tasks_.wait();\n  }\n\n private:\n  CurStage stage_;\n  LimitGatedScheduler tasks_;\n};\n\ntemplate <typename InputType, typename Stage0>\nauto makePipesHelper(ConcurrentTaskSet& tasks, Stage0&& sCur) {\n  return Pipe<StageClass::kSink, Stage0, SinkPipe>(tasks, std::forward<Stage0>(sCur));\n}\n\ntemplate <typename InputType, typename Stage0, typename Stage1, typename... Stages>\nauto makePipesHelper(\n    ConcurrentTaskSet& tasks,\n    Stage0&& sCur,\n    Stage1&& sNext,\n    Stages&&... sFollowing) {\n  using Stage0Result = ResultOf<Stage0, typename OptionalStrippedTraits<InputType>::Type>;\n\n  auto pipe = makePipesHelper<Stage0Result>(\n      tasks, std::forward<Stage1>(sNext), std::forward<Stages>(sFollowing)...);\n\n  constexpr StageClass kSc = TransformTraits<Stage0Result>::kStageClass;\n  return Pipe<kSc, Stage0, decltype(pipe)>(tasks, std::forward<Stage0>(sCur), std::move(pipe));\n}\n\ntemplate <typename Stage0, typename Stage1, typename... Stages>\nauto makePipes(ConcurrentTaskSet& tasks, Stage0&& sCur, Stage1&& sNext, Stages&&... sFollowing) {\n  auto pipe = makePipesHelper<ResultOf<Stage0>>(\n      tasks, std::forward<Stage1>(sNext), std::forward<Stages>(sFollowing)...);\n  return Pipe<StageClass::kGenerator, Stage0, decltype(pipe)>(\n      tasks, std::forward<Stage0>(sCur), std::move(pipe));\n}\n\ntemplate <typename Stage0>\nauto makePipes(ConcurrentTaskSet& tasks, Stage0&& sCur) {\n  return Pipe<StageClass::kSingleStage, Stage0, SinkPipe>(tasks, std::forward<Stage0>(sCur));\n}\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/quanta.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#ifdef _WIN32\n#include <Windows.h>\n#include <timeapi.h>\n#endif\n\n#include <dispenso/detail/quanta.h>\n\nnamespace dispenso {\n#ifdef _WIN32\n\nnamespace {\nstruct OsQuantaSetter {\n  OsQuantaSetter() {\n    timeBeginPeriod(1);\n  }\n  ~OsQuantaSetter() {\n    timeEndPeriod(1);\n  }\n};\n} // namespace\n#else\nnamespace {\nstruct OsQuantaSetter {};\n} // namespace\n\n#endif // _WIN32\n\nnamespace detail {\nvoid registerFineSchedulerQuanta() {\n  static OsQuantaSetter setter;\n  (void)setter;\n}\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/quanta.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\nnamespace dispenso {\nnamespace detail {\nvoid registerFineSchedulerQuanta();\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/result_of.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <type_traits>\n\nnamespace dispenso {\nnamespace detail {\n\n#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L\ntemplate <typename F, typename... Args>\nusing ResultOf = typename std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;\n#else\ntemplate <typename F, typename... Args>\nusing ResultOf =\n    typename std::result_of<typename std::decay<F>::type(typename std::decay<Args>::type...)>::type;\n#endif // c++17\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/rw_lock_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\nnamespace detail {\nclass RWLockImpl {\n public:\n  /**\n   * Locks for write access\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  void lock();\n\n  /**\n   * Tries to lock for write access, returns if unable to lock\n   *\n   * @return true if lock was acquired, false otherwise\n   **/\n  bool try_lock();\n\n  /**\n   * Unlocks write access\n   *\n   * @note Must already be locked by the current thread of execution, otherwise, the behavior is\n   * undefined.\n   **/\n  void unlock();\n\n  /**\n   * Locks for read access\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  void lock_shared();\n\n  /**\n   * Tries to lock for read access, returns if unable to lock\n   *\n   * @return true if lock was acquired, false otherwise\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  bool try_lock_shared();\n\n  /**\n   * Unlocks read access\n   *\n   * @note Must already be locked by the current thread of execution, otherwise, the behavior is\n   * undefined.\n   **/\n  void unlock_shared();\n\n  /**\n   * Upgrade from a reader lock to a writer lock.  lock_upgrade is a power-user interface.  There is\n   * a very good reason why it is not exposed as upgrade_mutex in the standard.  To use it safely,\n   * you *MUST* ensure only one thread can try to lock for write concurrently.  If that cannot be\n   * guaranteed, you should unlock for read, and lock for write instead of using lock_upgrade to\n   * avoid potential deadlock.\n   *\n   * @note Calling this if the writer lock is already held, or if no reader lock is already held is\n   * undefined behavior.\n   **/\n  void lock_upgrade();\n\n  /**\n   * Downgrade the lock from a writer lock to a reader lock.\n   *\n   * @note Calling this if the writer lock is not held results in undefined behavior\n   **/\n  void lock_downgrade();\n\n private:\n  static constexpr uint32_t kWriteBit = 0x80000000;\n  static constexpr uint32_t kReaderBits = 0x7fffffff;\n  std::atomic<uint32_t> lock_{0};\n};\n\ninline void RWLockImpl::lock() {\n  uint32_t val = lock_.fetch_or(kWriteBit, std::memory_order_acq_rel);\n  while (val & kWriteBit) {\n    val = lock_.fetch_or(kWriteBit, std::memory_order_acq_rel);\n  }\n  // We've claimed single write ownership now.  We need to drain off readers\n  while (val != kWriteBit) {\n    val = lock_.load(std::memory_order_acquire);\n  }\n}\n\ninline bool RWLockImpl::try_lock() {\n  uint32_t val = lock_.fetch_or(kWriteBit, std::memory_order_acq_rel);\n  return !(val & kWriteBit);\n}\n\ninline void RWLockImpl::unlock() {\n  lock_.fetch_and(kReaderBits, std::memory_order_acq_rel);\n}\n\ninline void RWLockImpl::lock_shared() {\n  uint32_t val = lock_.fetch_add(1, std::memory_order_acq_rel);\n  while (val & kWriteBit) {\n    val = lock_.fetch_sub(1, std::memory_order_acq_rel);\n    while (val & kWriteBit) {\n      val = lock_.load(std::memory_order_acquire);\n    }\n\n    val = lock_.fetch_add(1, std::memory_order_acq_rel);\n  }\n}\n\ninline bool RWLockImpl::try_lock_shared() {\n  uint32_t val = lock_.fetch_add(1, std::memory_order_acq_rel);\n  if (val & kWriteBit) {\n    lock_.fetch_sub(1, std::memory_order_acq_rel);\n    return false;\n  }\n  return true;\n}\n\ninline void RWLockImpl::unlock_shared() {\n  lock_.fetch_sub(1, std::memory_order_acq_rel);\n}\n\ninline void RWLockImpl::lock_upgrade() {\n  uint32_t val = lock_.fetch_or(kWriteBit, std::memory_order_acq_rel);\n  while (val & kWriteBit) {\n    val = lock_.fetch_or(kWriteBit, std::memory_order_acq_rel);\n  }\n  // We've claimed single write ownership now.  We need to drain off readers, including ourself\n  lock_.fetch_sub(1, std::memory_order_acq_rel);\n  while (val != kWriteBit) {\n    val = lock_.load(std::memory_order_acquire);\n  }\n}\n\ninline void RWLockImpl::lock_downgrade() {\n  // Get reader ownership first\n  lock_.fetch_add(1, std::memory_order_acq_rel);\n  unlock();\n}\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/small_buffer_allocator_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <vector>\n\n#include <dispenso/detail/math.h>\n#include <dispenso/platform.h>\n#include <dispenso/tsan_annotations.h>\n\n#include <moodycamel/concurrentqueue.h>\n\nnamespace dispenso {\nnamespace detail {\n\nstruct SmallBufferGlobals {\n  moodycamel::ConcurrentQueue<char*> centralStore;\n  std::vector<char*> backingStore;\n  std::atomic<uint32_t> backingStoreLock{0};\n\n  ~SmallBufferGlobals() {\n    for (char* b : backingStore) {\n      alignedFree(b);\n    }\n  }\n};\n\ntemplate <size_t kChunkSize>\nDISPENSO_DLL_ACCESS SmallBufferGlobals& getSmallBufferGlobals();\n\n/**\n * A class for allocating small chunks of memory quickly.  The class is built on concepts of\n * thread-local pools of buffers of specific sizes.  It is best to limit the distinct number of\n * sizes of chunk sizes used in one program or there is a good chance that there may be a lot of\n * unused memory allocated in the system.\n *\n * <code>SmallBufferAllocator</code> is completely thread-safe.\n **/\ntemplate <size_t kChunkSize>\nclass SmallBufferAllocator {\n private:\n  static constexpr size_t kLogFactor = log2const(kChunkSize | 1);\n\n  // TODO(T88183021): Make these factors compile-time configurable.  For example, the current values\n  // can lead to megabytes of data being allocated, even if the allocator is only used for one or\n  // two allocations.  Likely we can reduce these sizes by a decent factor without affecting\n  // benchmarks, and then reduce them even further as an option.\n  static constexpr size_t kMallocBytes = (1 << 12) * kLogFactor;\n  static constexpr size_t kIdealTLCacheBytes = kMallocBytes / 4;\n  static constexpr size_t kIdealNumTLBuffers = kIdealTLCacheBytes / kChunkSize;\n  static constexpr size_t kMaxNumTLBuffers = 2 * kIdealNumTLBuffers;\n  static constexpr size_t kBuffersPerMalloc = kMallocBytes / kChunkSize;\n\n  static_assert(kIdealNumTLBuffers > 0, \"Must have a positive number of buffers to work with\");\n\n public:\n  /**\n   * Allocate a buffer of <code>kChunkSize</code> bytes.\n   *\n   * @return a pointer to the buffer.\n   **/\n  static char* alloc() {\n    auto bnc = buffersAndCount();\n    char** tlBuffers = std::get<0>(bnc);\n    size_t& tlCount = std::get<1>(bnc);\n    if (!tlCount) {\n      // We only need to register (at least) once when we grab from the central store; without going\n      // to the central store at least once (or calling dealloc first), we cannot have buffers to\n      // return.\n      registerCleanup();\n      tlCount = grabFromCentralStore(tlBuffers);\n    }\n    return tlBuffers[--tlCount];\n  }\n\n  /**\n   * Deallocate a buffer previously allocated via <code>alloc</code>\n   *\n   * @param buffer The buffer to deallocate.\n   **/\n  static void dealloc(char* buffer) {\n    // We need to register at least once for any call to dealloc, because we may dealloc on this\n    // thread without having allocated on the same thread, and if we don't register, any memory in\n    // the thread-local buffers will not be returned to the central store on thread destruction.\n    auto bnc = buffersAndCount();\n    char** tlBuffers = std::get<0>(bnc);\n    size_t& tlCount = std::get<1>(bnc);\n    registerCleanup();\n    tlBuffers[tlCount++] = buffer;\n    if (tlCount == kMaxNumTLBuffers) {\n      recycleToCentralStore(tlBuffers + kIdealNumTLBuffers, kIdealNumTLBuffers);\n      tlCount -= kIdealNumTLBuffers;\n    }\n  }\n\n  /**\n   * Get the approximate number of underlying bytes allocated by the allocator.  This is mostly for\n   * testing and debugging.\n   *\n   * @return The approximate number of bytes currently allocated.\n   **/\n  static size_t bytesAllocated() {\n    uint32_t allocId = 0;\n    auto& globals = getSmallBufferGlobals<kChunkSize>();\n    auto& lock = globals.backingStoreLock;\n    while (!lock.compare_exchange_weak(allocId, 1, std::memory_order_acquire)) {\n    }\n    size_t bytes = kMallocBytes * globals.backingStore.size();\n    lock.store(0, std::memory_order_release);\n    return bytes;\n  }\n\n private:\n  struct PerThreadQueuingData {\n    PerThreadQueuingData(\n        moodycamel::ConcurrentQueue<char*>& cstore,\n        std::tuple<char**, size_t&> buffersAndCount)\n        : cstore_(cstore),\n          buffers_(std::get<0>(buffersAndCount)),\n          count_(std::get<1>(buffersAndCount)) {\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n      new (ptokenBuf_) moodycamel::ProducerToken(cstore);\n      new (ctokenBuf_) moodycamel::ConsumerToken(cstore);\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n    }\n\n    ~PerThreadQueuingData();\n\n    void enqueue_bulk(char** buffers, size_t count) {\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n      cstore_.enqueue_bulk(ptoken(), buffers, count);\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n    }\n\n    size_t try_dequeue_bulk(char** buffers, size_t count) {\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n      size_t actual = cstore_.try_dequeue_bulk(ctoken(), buffers, count);\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n      return actual;\n    }\n\n   private:\n    moodycamel::ProducerToken& ptoken() {\n      return *reinterpret_cast<moodycamel::ProducerToken*>(ptokenBuf_);\n    }\n    moodycamel::ConsumerToken& ctoken() {\n      return *reinterpret_cast<moodycamel::ConsumerToken*>(ctokenBuf_);\n    }\n\n    moodycamel::ConcurrentQueue<char*>& cstore_;\n    alignas(moodycamel::ProducerToken) char ptokenBuf_[sizeof(moodycamel::ProducerToken)];\n    alignas(moodycamel::ConsumerToken) char ctokenBuf_[sizeof(moodycamel::ConsumerToken)];\n    char** buffers_;\n    size_t& count_;\n  };\n\n  static void registerCleanup() {\n    // Note that this would be better/cheaper as a static thread_local member; however, there are\n    // currently bugs in multiple compilers that prevent the destructor from being called properly\n    // in that context.  A workaround that appears to work more portably is to put this here, and\n    // ensure registerCleanup is called for any alloc or dealloc, even though this may have a small\n    // runtime cost.\n    (void)getThreadQueuingData();\n  }\n\n  static size_t grabFromCentralStore(char** buffers) {\n    auto& queue = getThreadQueuingData();\n    auto& globals = getSmallBufferGlobals<kChunkSize>();\n    auto& lock = globals.backingStoreLock;\n    auto& backingStore = globals.backingStore;\n    while (true) {\n      size_t grabbed = queue.try_dequeue_bulk(buffers, kIdealNumTLBuffers);\n      if (grabbed) {\n        return grabbed;\n      }\n      uint32_t allocId = lock.fetch_add(1, std::memory_order_acquire);\n      if (allocId == 0) {\n        char* buffer = reinterpret_cast<char*>(detail::alignedMalloc(kMallocBytes, kChunkSize));\n        backingStore.push_back(buffer);\n\n        constexpr size_t kNumToPush = kBuffersPerMalloc - kIdealNumTLBuffers;\n        char* topush[kNumToPush];\n        for (size_t i = 0; i < kNumToPush; ++i, buffer += kChunkSize) {\n          topush[i] = buffer;\n        }\n        queue.enqueue_bulk(topush, kNumToPush);\n        lock.store(0, std::memory_order_release);\n        for (size_t i = 0; i < kIdealNumTLBuffers; ++i, buffer += kChunkSize) {\n          buffers[i] = buffer;\n        }\n        return kIdealNumTLBuffers;\n      } else {\n        while (lock.load(std::memory_order_relaxed)) {\n          std::this_thread::yield();\n        }\n      }\n    }\n  }\n\n  static void recycleToCentralStore(char** buffers, size_t numToRecycle) {\n    getThreadQueuingData().enqueue_bulk(buffers, numToRecycle);\n    // TODO(bbudge): consider whether we need to do any garbage collection and return memory to\n    // the system.\n  }\n\n private:\n  DISPENSO_DLL_ACCESS static std::tuple<char**, size_t&> buffersAndCount() {\n    static DISPENSO_THREAD_LOCAL char* tlBuffers[kMaxNumTLBuffers];\n    static DISPENSO_THREAD_LOCAL size_t tlCount = 0;\n    return {tlBuffers, tlCount};\n  };\n  DISPENSO_DLL_ACCESS static PerThreadQueuingData& getThreadQueuingData() {\n    static thread_local PerThreadQueuingData data(\n        getSmallBufferGlobals<kChunkSize>().centralStore, buffersAndCount());\n    return data;\n  }\n};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/task_set_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file task_set.h\n * A file providing TaskSet and ConcurrentTaskSet.  These interfaces allow the user to\n * submit/schedule multiple closures and then wait on them.\n **/\n\n#pragma once\n\n#include <dispenso/thread_pool.h>\n\nnamespace dispenso {\n\nclass TaskSetBase;\n\nnamespace detail {\ntemplate <typename Result>\nclass FutureBase;\n\nclass LimitGatedScheduler;\n\nDISPENSO_DLL_ACCESS void pushThreadTaskSet(TaskSetBase* tasks);\nDISPENSO_DLL_ACCESS void popThreadTaskSet();\n\n} // namespace detail\n\nDISPENSO_DLL_ACCESS TaskSetBase* parentTaskSet();\n\nclass TaskSetBase {\n public:\n  TaskSetBase(\n      ThreadPool& p,\n      ParentCascadeCancel registerForParentCancel = ParentCascadeCancel::kOff,\n      ssize_t stealingLoadMultiplier = 4)\n      : pool_(p), taskSetLoadFactor_(stealingLoadMultiplier * p.numThreads()) {\n#if defined DISPENSO_DEBUG\n    assert(stealingLoadMultiplier > 0);\n    pool_.outstandingTaskSets_.fetch_add(1, std::memory_order_acquire);\n#endif\n\n    parent_ = (registerForParentCancel == ParentCascadeCancel::kOn) ? parentTaskSet() : nullptr;\n\n    if (parent_) {\n      parent_->registerChild(this);\n      if (parent_->canceled()) {\n        canceled_.store(true, std::memory_order_release);\n      }\n    }\n  }\n\n  TaskSetBase(TaskSetBase&& other) = delete;\n  TaskSetBase& operator=(TaskSetBase&& other) = delete;\n\n  ssize_t numPoolThreads() const {\n    return pool_.numThreads();\n  }\n\n  ThreadPool& pool() {\n    return pool_;\n  }\n\n  void cancel() {\n    canceled_.store(true, std::memory_order_release);\n    cancelChildren();\n  }\n\n  bool canceled() const {\n    return canceled_.load(std::memory_order_acquire);\n  }\n\n  /**\n   * Check whether an exception has been captured by this task set.\n   * When exceptions are disabled at compile time, this always returns false,\n   * allowing the compiler to eliminate exception-related branches entirely.\n   **/\n#if defined(__cpp_exceptions)\n  bool hasException() const {\n    return guardException_.load(std::memory_order_acquire) != kUnset;\n  }\n#else\n  constexpr bool hasException() const {\n    return false;\n  }\n#endif\n\n  ~TaskSetBase() {\n#if defined DISPENSO_DEBUG\n    pool_.outstandingTaskSets_.fetch_sub(1, std::memory_order_release);\n#endif\n\n    if (parent_) {\n      parent_->unregisterChild(this);\n    }\n  }\n\n protected:\n  template <typename F>\n  auto packageTask(F&& f) {\n    outstandingTaskCount_.fetch_add(1, std::memory_order_acquire);\n    return [this, f = std::move(f)]() mutable {\n      // Skip push/pop if this TaskSet is already the current parent on this\n      // thread. This happens with ConcurrentTaskSet self-recursion (scheduling\n      // tasks from within tasks on the same set), which is normal and expected.\n      // Only actual nesting of *different* TaskSets needs stack tracking.\n      bool pushed = (parentTaskSet() != this);\n      if (pushed) {\n        detail::pushThreadTaskSet(this);\n      }\n      if (!canceled_.load(std::memory_order_acquire)) {\n#if defined(__cpp_exceptions)\n        try {\n          f();\n        } catch (...) {\n          trySetCurrentException();\n        }\n#else\n        f();\n#endif // __cpp_exceptions\n      }\n      if (pushed) {\n        detail::popThreadTaskSet();\n      }\n      outstandingTaskCount_.fetch_sub(1, std::memory_order_release);\n    };\n  }\n\n  // Package a task without incrementing the counter (for bulk scheduling where\n  // the counter is incremented once for the entire batch).\n  template <typename F>\n  auto packageTaskNoIncrement(F&& f) {\n    return [this, f = std::move(f)]() mutable {\n      detail::pushThreadTaskSet(this);\n      if (!canceled_.load(std::memory_order_acquire)) {\n#if defined(__cpp_exceptions)\n        try {\n          f();\n        } catch (...) {\n          trySetCurrentException();\n        }\n#else\n        f();\n#endif // __cpp_exceptions\n      }\n      detail::popThreadTaskSet();\n      outstandingTaskCount_.fetch_sub(1, std::memory_order_release);\n    };\n  }\n\n  template <typename Generator>\n  void scheduleBulkImpl(size_t count, Generator&& gen, moodycamel::ProducerToken* token) {\n    if (count == 0) {\n      return;\n    }\n\n    ssize_t numPool = pool_.numThreads();\n    size_t chunkSize = static_cast<size_t>(numPool) + static_cast<size_t>(numPool) / 2;\n    if (chunkSize < 1) {\n      chunkSize = 1;\n    }\n\n    size_t i = 0;\n    while (i < count) {\n      if (canceled()) {\n        break;\n      }\n      ssize_t outstanding = outstandingTaskCount_.load(std::memory_order_relaxed);\n      ssize_t curWork = pool_.workRemaining_.load(std::memory_order_relaxed);\n      // Mirror the two-tier inline decision from ThreadPool::schedule():\n      // 1. TaskSet-level: outstandingTaskCount_ exceeds our own load factor\n      // 2. Pool recursive: tight quickLoadFactor (numThreads*1.5) when called from a pool\n      //    thread. Critical for nested patterns where inner scheduleBulk must throttle to\n      //    avoid flooding the pool queue and starving outer tasks.\n      // 3. Pool global: loose poolLoadFactor_ (numThreads*32) for non-recursive callers\n      if (outstanding > taskSetLoadFactor_ ||\n          (detail::PerPoolPerThreadInfo::isPoolRecursive(&pool_) &&\n           curWork > numPool + numPool / 2) ||\n          curWork > pool_.poolLoadFactor_.load(std::memory_order_relaxed)) {\n#if defined(__cpp_exceptions)\n        try {\n          gen(i)();\n        } catch (...) {\n          trySetCurrentException();\n        }\n#else\n        gen(i)();\n#endif // __cpp_exceptions\n        ++i;\n      } else {\n        ssize_t room = taskSetLoadFactor_ - outstanding;\n        size_t toEnqueue = std::min({count - i, chunkSize, static_cast<size_t>(room)});\n        if (toEnqueue == 0) {\n          toEnqueue = 1;\n        }\n        outstandingTaskCount_.fetch_add(static_cast<ssize_t>(toEnqueue), std::memory_order_acquire);\n        size_t base = i;\n        pool_.scheduleBulkEnqueue(\n            toEnqueue,\n            [this, &gen, base](size_t j) { return packageTaskNoIncrement(gen(base + j)); },\n            token);\n        i += toEnqueue;\n      }\n    }\n  }\n\n  DISPENSO_DLL_ACCESS void trySetCurrentException();\n  bool testAndResetException();\n\n  void registerChild(TaskSetBase* child) {\n    std::lock_guard<std::mutex> lk(mtx_);\n\n    child->prev_ = tail_;\n    child->next_ = nullptr;\n    if (tail_) {\n      tail_->next_ = child;\n      tail_ = child;\n    } else {\n      head_ = tail_ = child;\n    }\n  }\n\n  void unregisterChild(TaskSetBase* child) {\n    std::lock_guard<std::mutex> lk(mtx_);\n\n    if (child->prev_) {\n      child->prev_->next_ = child->next_;\n    } else {\n      // We're head\n      assert(child == head_);\n      head_ = child->next_;\n    }\n    if (child->next_) {\n      child->next_->prev_ = child->prev_;\n    } else {\n      // We're tail\n      assert(child == tail_);\n      tail_ = child->prev_;\n    }\n  }\n\n  void cancelChildren() {\n    std::lock_guard<std::mutex> lk(mtx_);\n\n    auto* node = head_;\n    while (node) {\n      node->cancel();\n      node = node->next_;\n    }\n  }\n\n  alignas(kCacheLineSize) std::atomic<ssize_t> outstandingTaskCount_{0};\n  alignas(kCacheLineSize) ThreadPool& pool_;\n  alignas(kCacheLineSize) std::atomic<bool> canceled_{false};\n  const ssize_t taskSetLoadFactor_;\n  // Always present to ensure stable ABI layout regardless of __cpp_exceptions.\n  enum ExceptionState { kUnset, kSetting, kSet };\n  std::atomic<ExceptionState> guardException_{kUnset};\n  std::exception_ptr exception_;\n\n  TaskSetBase* parent_;\n\n  // This mutex guards modifications/use of the intusive linked list between head_ and tail_\n  std::mutex mtx_;\n  TaskSetBase* head_{nullptr};\n  TaskSetBase* tail_{nullptr};\n\n  // prev_ and next_ are links in our *parent's* intrusive linked list.\n  TaskSetBase* prev_;\n  TaskSetBase* next_;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/detail/timed_task_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/thread_pool.h>\n\nnamespace dispenso {\nnamespace detail {\n\nenum FunctionFlags : uint32_t { kFFlagsNone = 0, kFFlagsDetached = 1, kFFlagsCancelled = 2 };\n\nstruct TimedTaskImpl {\n  alignas(kCacheLineSize) std::atomic<size_t> count{0};\n  std::atomic<size_t> timesToRun;\n  std::atomic<uint32_t> flags{kFFlagsNone};\n  std::atomic<uint32_t> inProgress{0};\n  double nextAbsTime;\n  double period;\n  bool steady;\n  std::function<void(std::shared_ptr<TimedTaskImpl>)> func;\n\n  template <typename F, typename Schedulable>\n  TimedTaskImpl(size_t times, double next, double per, F&& f, Schedulable& sched, bool stdy)\n      : timesToRun(times), nextAbsTime(next), period(per), steady(stdy) {\n    func = [&sched, f = std::move(f), this](std::shared_ptr<TimedTaskImpl> me) {\n      if (flags.load(std::memory_order_acquire) & kFFlagsCancelled) {\n        return;\n      }\n\n      inProgress.fetch_add(1, std::memory_order_acq_rel);\n\n      auto wrap = [&f, this, me = std::move(me)]() mutable {\n        if (!(flags.load(std::memory_order_acquire) & kFFlagsCancelled)) {\n          if (!f()) {\n            timesToRun.store(0, std::memory_order_release);\n            flags.fetch_or(kFFlagsCancelled, std::memory_order_acq_rel);\n            func = {};\n          }\n          count.fetch_add(1, std::memory_order_acq_rel);\n        }\n\n        inProgress.fetch_sub(1, std::memory_order_release);\n        me.reset();\n      };\n      sched.schedule(wrap, ForceQueuingTag());\n    };\n  }\n};\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/dispenso.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file dispenso.h\n * @brief Convenience header that includes all public dispenso headers.\n *\n * For finer-grained control over compile times, include individual headers instead.\n **/\n\n#pragma once\n\n// Core threading primitives\n#include <dispenso/future.h>\n#include <dispenso/schedulable.h>\n#include <dispenso/task_set.h>\n#include <dispenso/thread_pool.h>\n\n// Parallel algorithms\n#include <dispenso/for_each.h>\n#include <dispenso/parallel_for.h>\n#include <dispenso/pipeline.h>\n\n// Graph-based task scheduling\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n\n// Concurrent containers\n#include <dispenso/concurrent_object_arena.h>\n#include <dispenso/concurrent_vector.h>\n\n// Synchronization primitives\n#include <dispenso/completion_event.h>\n#include <dispenso/latch.h>\n#include <dispenso/rw_lock.h>\n\n// Memory management\n#include <dispenso/pool_allocator.h>\n#include <dispenso/resource_pool.h>\n#include <dispenso/small_buffer_allocator.h>\n\n// Async utilities\n#include <dispenso/async_request.h>\n#include <dispenso/once_function.h>\n#include <dispenso/timed_task.h>\n\n// Utilities\n#include <dispenso/platform.h>\n#include <dispenso/priority.h>\n#include <dispenso/thread_id.h>\n#include <dispenso/timing.h>\n#include <dispenso/util.h>\n\n// Sanitizer support\n#include <dispenso/tsan_annotations.h>\n"
  },
  {
    "path": "dispenso/fast_math/README.md",
    "content": "# dispenso::fast_math\n\n> **EXPERIMENTAL** — This sublibrary is under active development. The API is\n> unstable and subject to breaking changes without notice. Do not depend on it\n> in production code.\n>\n> fast_math is not built by default. To include it in the CMake build, set\n> `-DDISPENSO_BUILD_FAST_MATH=ON`.\n\nA fast, accurate, SIMD-friendly math library for `float` transcendentals.\n\n- [Design Goals](#design-goals)\n- [Quick Start](#quick-start)\n- [Accuracy Traits](#accuracy-traits)\n- [SIMD Support](#simd-support)\n- [Function Reference](#function-reference)\n- [Performance](#performance)\n\n## Design Goals\n\n- **Fast**: 1.5-6x faster than glibc scalar math, with near-linear SIMD scaling\n- **Accurate**: Drop-in replacements for `std::` math functions (1-4 ULP typical)\n- **SIMD-native**: Same template works for `float`, `__m128`, `__m256`, `__m512`,\n  `float32x4_t`, and Highway vectors — no source changes needed\n- **Configurable**: `AccuracyTraits` template parameter trades speed for precision\n  and edge-case handling at compile time\n\n## Quick Start\n\n```cpp\n#include <dispenso/fast_math/fast_math.h>\n\nnamespace dfm = dispenso::fast_math;\n\n// Scalar — drop-in replacement for std::sinf\nfloat y = dfm::sin(x);\n\n// SSE4.1 (4-wide) — same function, SIMD type\n__m128 y4 = dfm::sin(x4);\n\n// AVX2 (8-wide)\n__m256 y8 = dfm::sin(x8);\n\n// Max accuracy with bounds checking\nfloat y = dfm::sin<float, dfm::MaxAccuracyTraits>(x);\n```\n\nFor auto-detected best SIMD width:\n```cpp\n#include <dispenso/fast_math/simd.h>\n\nusing F = dispenso::fast_math::DefaultSimdFloat;\nF result = dispenso::fast_math::sin(F(1.0f));\n```\n\n## Accuracy Traits\n\nAll functions accept an optional `AccuracyTraits` template parameter:\n\n| Trait | `kMaxAccuracy` | `kBoundsValues` | Description |\n|:------|:-:|:-:|:---|\n| `DefaultAccuracyTraits` | false | false | Fastest. Correct over normal-range inputs. |\n| `MaxAccuracyTraits` | true | true | Highest accuracy + edge-case handling (NaN, Inf, denorm). |\n\nCustom traits can mix these independently:\n```cpp\nstruct BoundsOnly {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;  // Handle NaN/Inf, keep fast polynomials\n};\nfloat y = dfm::exp<float, BoundsOnly>(x);\n```\n\n## SIMD Support\n\n### Supported Types\n\n| Backend | Type | Width | Guard Macro |\n|:--------|:-----|:-----:|:------------|\n| Scalar | `float` | 1 | always |\n| SSE4.1 | `__m128` | 4 | `__SSE4_1__` |\n| AVX2 | `__m256` | 8 | `__AVX2__` |\n| AVX-512 | `__m512` | 16 | `__AVX512F__` |\n| NEON | `float32x4_t` | 4 | `__aarch64__` |\n| Highway | `HwyFloat` | variable | `__has_include(\"hwy/highway.h\")` |\n\nAll SIMD backends provide `FloatTraits` specializations with the required operations\n(`fma`, `sqrt`, `conditional`, `bit_cast`, etc.). Include `<dispenso/fast_math/fast_math.h>`\nand the appropriate backend headers are auto-included based on platform macros.\n\n### How It Works\n\nEvery function is templated on `Flt`. When `Flt` is a SIMD vector type, all\noperations (arithmetic, comparisons, bit manipulation) dispatch through\n`FloatTraits<Flt>` specializations that map to the corresponding intrinsics.\nPolynomial coefficients stay as scalar `float` arrays — the implicit\n`SseFloat(float)` / `_mm256_set1_ps` broadcast is efficient on modern hardware.\n\n## Function Reference\n\n### Trigonometric\n\n| Function | Signature | Domain | Max ULP (Default) | Max ULP (MaxAccuracy) |\n|:---------|:----------|:-------|:--:|:--:|\n| `sin` | `sin(x)` | all float | 1 ([-128pi,128pi]), 2 ([-1Mpi,1Mpi]) | 1 ([-1Mpi,1Mpi]), 2 (full) |\n| `cos` | `cos(x)` | all float | 1 ([-128pi,128pi]), 2 ([-1Mpi,1Mpi]) | 1 ([-128pi,128pi]), 2 ([-1Mpi,1Mpi]) |\n| `tan` | `tan(x)` | all float | 3 ([-128Kpi,128Kpi]), 32 ([-1Mpi,1Mpi]) | 3 ([-128Kpi,128Kpi]), 4 ([-1Mpi,1Mpi]) |\n\n### Inverse Trigonometric\n\n| Function | Signature | Domain | Max ULP |\n|:---------|:----------|:-------|:--:|\n| `acos` | `acos(x)` | [-1, 1] | 3 |\n| `asin` | `asin(x)` | [-1, 1] | 2 |\n| `atan` | `atan(x)` | all float | 3 |\n| `atan2` | `atan2(y, x)` | all float | 3 (Default), 3 (MaxAccuracy, +Inf handling) |\n\n### Exponential\n\n| Function | Signature | Domain | Max ULP (Default) | Max ULP (MaxAccuracy) |\n|:---------|:----------|:-------|:--:|:--:|\n| `exp` | `exp(x)` | [-89, 89] | 3 | 1 |\n| `exp2` | `exp2(x)` | [-127, 128] | 1 | 1 |\n| `exp10` | `exp10(x)` | [-40, 40] | 2 | 2 |\n| `expm1` | `expm1(x)` | all float | 2 | 1 |\n\nWith `kBoundsValues = true`, exp/exp2/exp10 correctly handle NaN, +/-Inf, and\nout-of-range inputs (returning 0 for large negative, Inf for large positive).\n\n`expm1` computes exp(x) - 1 with precision near zero using Cody-Waite range\nreduction and Sollya-optimized polynomials. For x < -17, returns -1 exactly\n(exp(x) is below float ULP of 1).\n\n### Logarithmic\n\n| Function | Signature | Domain | Max ULP (Default) | Max ULP (MaxAccuracy) |\n|:---------|:----------|:-------|:--:|:--:|\n| `log` | `log(x)` | (0, +Inf) | 2 | 2 |\n| `log1p` | `log1p(x)` | (-1, +Inf) | 2 | 2 |\n| `log2` | `log2(x)` | (0, +Inf) | 1 | 1 |\n| `log10` | `log10(x)` | (0, +Inf) | 3 | 3 |\n\nWith `kBoundsValues = true`, log/log2/log10 correctly handle 0, denormals,\nInf, and NaN inputs.\n\n`log1p` computes log(1 + x) with precision near zero using compensated\naddition: captures the rounding error of 1 + x and applies a first-order\ncorrection. Bounds handling inherited from log.\n\n### Other\n\n| Function | Signature | Domain | Max ULP (Default) | Max ULP (MaxAccuracy) |\n|:---------|:----------|:-------|:--:|:--:|\n| `sqrt` | `sqrt(x)` | all float | 0 | 0 |\n| `cbrt` | `cbrt(x)` | all float | 12 | 3 |\n| `hypot` | `hypot(x, y)` | all float | 1 | 1 |\n| `pow` | `pow(x, y)` | all float | 1 | 1 |\n| `tanh` | `tanh(x)` | all float | 2 | 2 |\n| `erf` | `erf(x)` | all float | 2 | 2 |\n| `frexp` | `frexp(x, &e)` | all float | 0 | 0 |\n| `ldexp` | `ldexp(x, e)` | all float | 0 | 0 |\n\n`sqrt` delegates to hardware `sqrt`. `frexp` and `ldexp` are bit-accurate.\n\n`hypot` uses double-precision cast for scalar and dynamic exponent\nscaling with Newton refinement for SIMD (~1 ULP). Overflow-safe for all normal\nfloats (up to ~2^126). With `kBoundsValues = true`, hypot correctly handles\nIEEE 754 boundary conditions: `hypot(±inf, y) = +inf` even when `y` is NaN,\nand `hypot(NaN, finite) = NaN`.\n\n`pow` uses double-precision arithmetic internally for ~1 ULP across all SIMD\nbackends. Scalar uses a table-based double core; SIMD uses width-dependent\ndispatch (table-assisted for ≤4 lanes, fully tableless for ≥8 lanes).\nWith `kBoundsValues = true`, handles all IEEE 754 special cases (negative\nbase, zero, inf, NaN, subnormals).\n\n`tanh` uses `expm1(2x) / (expm1(2x) + 2)` with a Sollya-optimized polynomial\nfast-path for scalar |x| < 1. Saturates to ±1 for |x| > 10.\n\n`erf` uses an Abramowitz & Stegun 7.1.26-inspired t-substitution with\nSollya-optimized coefficients (p=0.45). Two domains: pure polynomial for\n|x| < 0.875, erfc formula with inline exp(-x²) for |x| ∈ [0.875, 3.92].\nNaN propagates naturally via `clamp_allow_nan` (no `kBoundsValues` overhead).\nDefault and MaxAccuracy are identical.\n\n## Performance\n\nSpeedup ratios relative to platform libc (scalar) or scalar fast_math (SIMD).\nAbsolute throughput varies by clock speed and microarchitecture; ratios are\nmore meaningful for comparison.\n\n### Linux x86-64 — AMD EPYC Genoa\n\n166 cores, clang 21.1.7, `-O2 -march=native`, CMake Release build.\n\n#### Scalar: fast_math vs glibc\n\n| Function | Speedup | Function | Speedup |\n|:---------|:-:|:---------|:-:|\n| sin | 1.6x | exp | 3.8x |\n| cos | 1.6x | exp2 | 2.7x |\n| tan | 2.9x | exp10 | 2.5x |\n| acos | 2.2x | log | 3.4x |\n| asin | 3.4x | log2 | 3.0x |\n| atan | 1.7x | log10 | 3.3x |\n| atan2 | 3.3x | cbrt | 5.6x |\n| frexp | 3.8x | ldexp | 5.8x |\n| hypot | 2.3x | pow | 1.2x |\n| expm1 | 2.4x | log1p | 1.4x |\n| tanh | 3.0x | | |\n| erf | 1.6x | | |\n\n#### SIMD Scaling (per-element throughput relative to scalar fast_math)\n\n| Function | SSE (4) | AVX (8) | AVX-512 (16) | Highway (16) |\n|:---------|:-:|:-:|:-:|:-:|\n| sin | 2.7x | 5.4x | 6.5x | 5.8x |\n| cos | 2.6x | 5.2x | 6.5x | 5.7x |\n| tan | 3.6x | 7.0x | 8.7x | 7.7x |\n| acos | 4.9x | 9.8x | 10.1x | 10.2x |\n| asin | 1.9x | 3.8x | 4.3x | 4.3x |\n| atan | 4.8x | 9.5x | 11.9x | 11.9x |\n| atan2 | 3.5x | 7.0x | 9.6x | 9.6x |\n| exp | 3.7x | 7.4x | 7.7x | 7.3x |\n| exp2 | 3.7x | 7.5x | 8.8x | 7.2x |\n| exp10 | 3.7x | 7.3x | 8.6x | 7.1x |\n| log | 3.7x | 7.4x | 8.8x | 8.8x |\n| log2 | 3.6x | 7.3x | 9.6x | 9.6x |\n| log10 | 3.7x | 7.4x | 9.2x | 9.2x |\n| cbrt | 2.9x | 5.7x | 7.0x | 7.1x |\n| frexp | 7.4x | 14.8x | 23.0x | 22.9x |\n| ldexp | 4.8x | 9.7x | 16.6x | 16.6x |\n| hypot | 3.6x | — | 9.9x | — |\n| pow | — | 3.6x | 7.2x | — |\n| expm1 | 2.7x | 5.4x | 10.4x | 9.4x |\n| log1p | 3.0x | 6.0x | 12.5x | 12.4x |\n| tanh | 3.0x | 6.1x | 12.2x | 10.1x |\n| erf | 2.4x | 5.1x | 5.5x | 4.9x |\n\nHighway dispatches to AVX-512 (16-lane) on this hardware.\n\n#### Highway vs hwy::contrib (AVX-512 dispatch)\n\n| Function | Ratio | Function | Ratio |\n|:---------|:-:|:---------|:-:|\n| sin | 0.76x | log | 1.60x |\n| cos | 0.74x | log2 | 1.62x |\n| exp | 1.63x | log10 | 1.67x |\n| exp2 | 2.21x | atan | 1.12x |\n| acos | 1.63x | asin | 0.87x |\n| atan2 | 1.67x | | |\n\nfast_math is 1.6-2.2x faster for exp/log family, comparable for inverse trig,\nand ~25% slower for sin/cos (contrib uses a different polynomial fit).\n\n#### MaxAccuracyTraits overhead (SSE4.1)\n\n| Function | Overhead | Function | Overhead |\n|:---------|:-:|:---------|:-:|\n| sin | ~0% | log | 46% |\n| cos | ~0% | cbrt | 24% |\n| exp | 37% | hypot | 18% (SSE), 29% (AVX-512) |\n\n### Mac ARM — Apple M4 Pro\n\n12 cores, 48 GB, Apple clang, `-O2`.\n\n#### Scalar: fast_math vs Apple libm\n\n| Function | Speedup | Function | Speedup |\n|:---------|:-:|:---------|:-:|\n| sin | 1.0x | exp | 1.7x |\n| cos | 1.4x | exp2 | 1.7x |\n| tan | 1.2x | exp10 | 1.6x |\n| acos | 1.6x | log | 1.6x |\n| asin | 1.8x | log2 | 1.0x |\n| atan | 1.8x | log10 | 1.6x |\n| atan2 | 1.7x | cbrt | 2.6x |\n| frexp | 1.4x | ldexp | 2.0x |\n| hypot | 1.6x | | |\n\nApple's libm is highly optimized for M-series silicon; the smaller speedups\nreflect a stronger baseline rather than slower fast_math.\n\n#### SIMD Scaling (per-element throughput relative to scalar fast_math)\n\n| Function | NEON (4) | Highway (4) |\n|:---------|:-:|:-:|\n| sin | 5.4x | 4.9x |\n| cos | 3.7x | 3.5x |\n| tan | 4.6x | 4.1x |\n| acos | 4.8x | 3.5x |\n| asin | 2.8x | 2.9x |\n| atan | 3.4x | 2.3x |\n| atan2 | 2.2x | 1.3x |\n| exp | 3.9x | 3.6x |\n| exp2 | 4.0x | 3.9x |\n| exp10 | 3.9x | 2.7x |\n| log | 4.4x | 2.7x |\n| log2 | 3.5x | 1.1x |\n| log10 | 2.5x | 1.6x |\n| cbrt | 3.1x | 2.4x |\n| frexp | 4.0x | 4.3x |\n| ldexp | 4.0x | 4.0x |\n| hypot | 2.1x | — |\n\nHighway dispatches to NEON (4-lane) on AArch64. NEON backend is generally\nfaster than Highway on ARM due to lower abstraction overhead.\n"
  },
  {
    "path": "dispenso/fast_math/detail/double_promote.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// DoubleVec<Flt>: a pair of double-precision vectors covering all lanes of Flt.\n//\n// Provides the minimal set of operations needed for the tableless\n// double-precision pow core: widen, narrow, arithmetic, FMA, and\n// exp2 range-reduction helpers.\n//\n// Specialized for each SIMD backend alongside its float type:\n//   float     → double (scalar)\n//   SseFloat  → __m128d lo, hi\n//   AvxFloat  → __m256d lo, hi\n//   Avx512Float → __m512d lo, hi\n//   NeonFloat → float64x2_t lo, hi\n//   HwyFloat  → Vec<Repartition<double, FloatTag>> lo, hi\n\n#pragma once\n\n#include <cmath>\n#include <cstdint>\n#include <utility>\n\n#include <dispenso/fast_math/util.h>\n\nnamespace dispenso {\nnamespace fast_math {\nnamespace detail {\n\n// Primary template — undefined; each backend specializes.\ntemplate <typename Flt>\nstruct DoubleVec;\n\n// ---------------------------------------------------------------------------\n// Scalar: DoubleVec<float> is just a double.\n// ---------------------------------------------------------------------------\ntemplate <>\nstruct DoubleVec<float> {\n  double v;\n\n  DoubleVec() = default;\n  explicit DoubleVec(double d) : v(d) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(float f) {\n    return DoubleVec{static_cast<double>(f)};\n  }\n\n  // Gather: load table[index] as a double.\n  static DISPENSO_INLINE DoubleVec gather(const double* base, int32_t index) {\n    return DoubleVec{base[index]};\n  }\n\n  DISPENSO_INLINE float to_float() const {\n    return static_cast<float>(v);\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return DoubleVec{a.v + b.v};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return DoubleVec{a.v - b.v};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return DoubleVec{a.v * b.v};\n  }\n\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n    return DoubleVec{std::fma(a.v, b.v, c.v)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return DoubleVec{x.v < low.v ? low.v : (x.v > high.v ? high.v : x.v)};\n  }\n};\n\n// exp2 range reduction: free function, defined after DoubleVec is complete.\n// Splits x into integer n and fractional r ∈ [-0.5, 0.5].\n// Returns {r, scale} where scale = 2^n.\n// Boundary cases (from ylogx clamped to [-1022, 1023]):\n//   n = 1024 → scale = +inf (0x7FF0...), result overflows to +inf — correct.\n//   n = -1023 → scale = 0.0, result underflows to 0 — correct.\nDISPENSO_INLINE std::pair<DoubleVec<float>, DoubleVec<float>> exp2_split(DoubleVec<float> x) {\n  using DV = DoubleVec<float>;\n  constexpr double kShift = 0x1.8p+52;\n  constexpr uint64_t kShiftBits = 0x4338000000000000ULL;\n\n  double shifted = x.v + kShift;\n  uint64_t ki = bit_cast<uint64_t>(shifted);\n  double nd = shifted - kShift;\n  double r = x.v - nd;\n\n  int64_t n = static_cast<int64_t>(ki - kShiftBits);\n  double scale = bit_cast<double>(static_cast<uint64_t>(n + 1023) << 52);\n\n  return {DV{r}, DV{scale}};\n}\n\n// ---------------------------------------------------------------------------\n// SSE: DoubleVec<SseFloat> holds two __m128d (4 float lanes → 2×2 doubles).\n// ---------------------------------------------------------------------------\n#if defined(__SSE4_1__)\n\ntemplate <>\nstruct DoubleVec<SseFloat> {\n  __m128d lo, hi; // lo = lanes 0,1; hi = lanes 2,3\n\n  DoubleVec() = default;\n  DoubleVec(__m128d l, __m128d h) : lo(l), hi(h) {}\n  explicit DoubleVec(double d) : lo(_mm_set1_pd(d)), hi(_mm_set1_pd(d)) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(SseFloat f) {\n    return {_mm_cvtps_pd(f.v), _mm_cvtps_pd(_mm_movehl_ps(f.v, f.v))};\n  }\n\n  // Gather: load base[idx[lane]] for each of 4 lanes via scalar lookups.\n  // Used for small tables that fit in L1 (e.g. 16-entry pow log2 table).\n  static DISPENSO_INLINE DoubleVec gather(const double* base, SseInt32 idx) {\n    int32_t i0 = _mm_extract_epi32(idx.v, 0);\n    int32_t i1 = _mm_extract_epi32(idx.v, 1);\n    int32_t i2 = _mm_extract_epi32(idx.v, 2);\n    int32_t i3 = _mm_extract_epi32(idx.v, 3);\n    return {_mm_set_pd(base[i1], base[i0]), _mm_set_pd(base[i3], base[i2])};\n  }\n\n  DISPENSO_INLINE SseFloat to_float() const {\n    __m128 lo_f = _mm_cvtpd_ps(lo);\n    __m128 hi_f = _mm_cvtpd_ps(hi);\n    return SseFloat{_mm_movelh_ps(lo_f, hi_f)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return {_mm_add_pd(a.lo, b.lo), _mm_add_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return {_mm_sub_pd(a.lo, b.lo), _mm_sub_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return {_mm_mul_pd(a.lo, b.lo), _mm_mul_pd(a.hi, b.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n#if defined(__FMA__)\n    return {_mm_fmadd_pd(a.lo, b.lo, c.lo), _mm_fmadd_pd(a.hi, b.hi, c.hi)};\n#else\n    return {_mm_add_pd(_mm_mul_pd(a.lo, b.lo), c.lo), _mm_add_pd(_mm_mul_pd(a.hi, b.hi), c.hi)};\n#endif\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return {\n        _mm_min_pd(_mm_max_pd(x.lo, low.lo), high.lo),\n        _mm_min_pd(_mm_max_pd(x.hi, low.hi), high.hi)};\n  }\n};\n\nDISPENSO_INLINE std::pair<DoubleVec<SseFloat>, DoubleVec<SseFloat>> exp2_split(\n    DoubleVec<SseFloat> x) {\n  using DV = DoubleVec<SseFloat>;\n  __m128d kShift = _mm_set1_pd(0x1.8p+52);\n  __m128i kShiftBits = _mm_set1_epi64x(0x4338000000000000LL);\n  __m128i k1023 = _mm_set1_epi64x(1023);\n\n  __m128d shifted_lo = _mm_add_pd(x.lo, kShift);\n  __m128d shifted_hi = _mm_add_pd(x.hi, kShift);\n\n  __m128i ki_lo = _mm_castpd_si128(shifted_lo);\n  __m128i ki_hi = _mm_castpd_si128(shifted_hi);\n\n  __m128d nd_lo = _mm_sub_pd(shifted_lo, kShift);\n  __m128d nd_hi = _mm_sub_pd(shifted_hi, kShift);\n\n  __m128d r_lo = _mm_sub_pd(x.lo, nd_lo);\n  __m128d r_hi = _mm_sub_pd(x.hi, nd_hi);\n\n  __m128i n_lo = _mm_sub_epi64(ki_lo, kShiftBits);\n  __m128i n_hi = _mm_sub_epi64(ki_hi, kShiftBits);\n\n  __m128d scale_lo = _mm_castsi128_pd(_mm_slli_epi64(_mm_add_epi64(n_lo, k1023), 52));\n  __m128d scale_hi = _mm_castsi128_pd(_mm_slli_epi64(_mm_add_epi64(n_hi, k1023), 52));\n\n  return {DV{r_lo, r_hi}, DV{scale_lo, scale_hi}};\n}\n\n#endif // __SSE4_1__\n\n// ---------------------------------------------------------------------------\n// AVX: DoubleVec<AvxFloat> holds two __m256d (8 float lanes → 2×4 doubles).\n// ---------------------------------------------------------------------------\n#if defined(__AVX2__)\n\ntemplate <>\nstruct DoubleVec<AvxFloat> {\n  __m256d lo, hi; // lo = lanes 0-3; hi = lanes 4-7\n\n  DoubleVec() = default;\n  DoubleVec(__m256d l, __m256d h) : lo(l), hi(h) {}\n  explicit DoubleVec(double d) : lo(_mm256_set1_pd(d)), hi(_mm256_set1_pd(d)) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(AvxFloat f) {\n    return {\n        _mm256_cvtps_pd(_mm256_castps256_ps128(f.v)),\n        _mm256_cvtps_pd(_mm256_extractf128_ps(f.v, 1))};\n  }\n\n  // Gather: AVX2 has native 4-wide double gather from int32 indices.\n  // Two gathers cover all 8 lanes. The table is 256 bytes (4 cachelines),\n  // likely L1-hot after the first call.\n  static DISPENSO_INLINE DoubleVec gather(const double* base, AvxInt32 idx) {\n    __m128i lo4 = _mm256_castsi256_si128(idx.v);\n    __m128i hi4 = _mm256_extracti128_si256(idx.v, 1);\n    return {_mm256_i32gather_pd(base, lo4, 8), _mm256_i32gather_pd(base, hi4, 8)};\n  }\n\n  DISPENSO_INLINE AvxFloat to_float() const {\n    __m128 lo_f = _mm256_cvtpd_ps(lo);\n    __m128 hi_f = _mm256_cvtpd_ps(hi);\n    return AvxFloat{_mm256_set_m128(hi_f, lo_f)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return {_mm256_add_pd(a.lo, b.lo), _mm256_add_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return {_mm256_sub_pd(a.lo, b.lo), _mm256_sub_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return {_mm256_mul_pd(a.lo, b.lo), _mm256_mul_pd(a.hi, b.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n#if defined(__FMA__)\n    return {_mm256_fmadd_pd(a.lo, b.lo, c.lo), _mm256_fmadd_pd(a.hi, b.hi, c.hi)};\n#else\n    return {\n        _mm256_add_pd(_mm256_mul_pd(a.lo, b.lo), c.lo),\n        _mm256_add_pd(_mm256_mul_pd(a.hi, b.hi), c.hi)};\n#endif\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return {\n        _mm256_min_pd(_mm256_max_pd(x.lo, low.lo), high.lo),\n        _mm256_min_pd(_mm256_max_pd(x.hi, low.hi), high.hi)};\n  }\n};\n\nDISPENSO_INLINE std::pair<DoubleVec<AvxFloat>, DoubleVec<AvxFloat>> exp2_split(\n    DoubleVec<AvxFloat> x) {\n  using DV = DoubleVec<AvxFloat>;\n  __m256d kShift = _mm256_set1_pd(0x1.8p+52);\n  __m256i kShiftBits = _mm256_set1_epi64x(0x4338000000000000LL);\n  __m256i k1023 = _mm256_set1_epi64x(1023);\n\n  __m256d shifted_lo = _mm256_add_pd(x.lo, kShift);\n  __m256d shifted_hi = _mm256_add_pd(x.hi, kShift);\n\n  __m256i ki_lo = _mm256_castpd_si256(shifted_lo);\n  __m256i ki_hi = _mm256_castpd_si256(shifted_hi);\n\n  __m256d nd_lo = _mm256_sub_pd(shifted_lo, kShift);\n  __m256d nd_hi = _mm256_sub_pd(shifted_hi, kShift);\n\n  __m256d r_lo = _mm256_sub_pd(x.lo, nd_lo);\n  __m256d r_hi = _mm256_sub_pd(x.hi, nd_hi);\n\n  __m256i n_lo = _mm256_sub_epi64(ki_lo, kShiftBits);\n  __m256i n_hi = _mm256_sub_epi64(ki_hi, kShiftBits);\n\n  __m256d scale_lo = _mm256_castsi256_pd(_mm256_slli_epi64(_mm256_add_epi64(n_lo, k1023), 52));\n  __m256d scale_hi = _mm256_castsi256_pd(_mm256_slli_epi64(_mm256_add_epi64(n_hi, k1023), 52));\n\n  return {DV{r_lo, r_hi}, DV{scale_lo, scale_hi}};\n}\n\n#endif // __AVX2__\n\n// ---------------------------------------------------------------------------\n// AVX-512: DoubleVec<Avx512Float> holds two __m512d (16 floats → 2×8 doubles).\n// ---------------------------------------------------------------------------\n#if defined(__AVX512F__)\n\ntemplate <>\nstruct DoubleVec<Avx512Float> {\n  __m512d lo, hi; // lo = lanes 0-7; hi = lanes 8-15\n\n  DoubleVec() = default;\n  DoubleVec(__m512d l, __m512d h) : lo(l), hi(h) {}\n  explicit DoubleVec(double d) : lo(_mm512_set1_pd(d)), hi(_mm512_set1_pd(d)) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(Avx512Float f) {\n    __m256 lo8 = _mm512_castps512_ps256(f.v);\n    // Extract upper 8 floats without requiring AVX-512 DQ:\n    // cast to __m512i, extract upper 256-bit int lane, reinterpret as __m256.\n    __m256 hi8 = _mm256_castsi256_ps(_mm512_extracti64x4_epi64(_mm512_castps_si512(f.v), 1));\n    return {_mm512_cvtps_pd(lo8), _mm512_cvtps_pd(hi8)};\n  }\n\n  // Gather: AVX-512 has native 8-wide double gather from int32 indices.\n  // Two gathers cover all 16 lanes.\n  static DISPENSO_INLINE DoubleVec gather(const double* base, Avx512Int32 idx) {\n    __m256i lo8 = _mm512_castsi512_si256(idx.v);\n    __m256i hi8 = _mm512_extracti64x4_epi64(idx.v, 1);\n    return {_mm512_i32gather_pd(lo8, base, 8), _mm512_i32gather_pd(hi8, base, 8)};\n  }\n\n  DISPENSO_INLINE Avx512Float to_float() const {\n    __m256 lo_f = _mm512_cvtpd_ps(lo);\n    __m256 hi_f = _mm512_cvtpd_ps(hi);\n    // Combine without AVX-512 DQ: cast to int, insert, cast back.\n    __m512i combined = _mm512_inserti64x4(\n        _mm512_castsi256_si512(_mm256_castps_si256(lo_f)), _mm256_castps_si256(hi_f), 1);\n    return Avx512Float{_mm512_castsi512_ps(combined)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return {_mm512_add_pd(a.lo, b.lo), _mm512_add_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return {_mm512_sub_pd(a.lo, b.lo), _mm512_sub_pd(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return {_mm512_mul_pd(a.lo, b.lo), _mm512_mul_pd(a.hi, b.hi)};\n  }\n\n  // AVX-512 always has FMA.\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n    return {_mm512_fmadd_pd(a.lo, b.lo, c.lo), _mm512_fmadd_pd(a.hi, b.hi, c.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return {\n        _mm512_min_pd(_mm512_max_pd(x.lo, low.lo), high.lo),\n        _mm512_min_pd(_mm512_max_pd(x.hi, low.hi), high.hi)};\n  }\n};\n\nDISPENSO_INLINE std::pair<DoubleVec<Avx512Float>, DoubleVec<Avx512Float>> exp2_split(\n    DoubleVec<Avx512Float> x) {\n  using DV = DoubleVec<Avx512Float>;\n  __m512d kShift = _mm512_set1_pd(0x1.8p+52);\n  __m512i kShiftBits = _mm512_set1_epi64(0x4338000000000000LL);\n  __m512i k1023 = _mm512_set1_epi64(1023);\n\n  __m512d shifted_lo = _mm512_add_pd(x.lo, kShift);\n  __m512d shifted_hi = _mm512_add_pd(x.hi, kShift);\n\n  __m512i ki_lo = _mm512_castpd_si512(shifted_lo);\n  __m512i ki_hi = _mm512_castpd_si512(shifted_hi);\n\n  __m512d nd_lo = _mm512_sub_pd(shifted_lo, kShift);\n  __m512d nd_hi = _mm512_sub_pd(shifted_hi, kShift);\n\n  __m512d r_lo = _mm512_sub_pd(x.lo, nd_lo);\n  __m512d r_hi = _mm512_sub_pd(x.hi, nd_hi);\n\n  __m512i n_lo = _mm512_sub_epi64(ki_lo, kShiftBits);\n  __m512i n_hi = _mm512_sub_epi64(ki_hi, kShiftBits);\n\n  __m512d scale_lo = _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_add_epi64(n_lo, k1023), 52));\n  __m512d scale_hi = _mm512_castsi512_pd(_mm512_slli_epi64(_mm512_add_epi64(n_hi, k1023), 52));\n\n  return {DV{r_lo, r_hi}, DV{scale_lo, scale_hi}};\n}\n\n#endif // __AVX512F__\n\n// ---------------------------------------------------------------------------\n// NEON: DoubleVec<NeonFloat> holds two float64x2_t (4 floats → 2×2 doubles).\n// ---------------------------------------------------------------------------\n#if defined(__aarch64__)\n\ntemplate <>\nstruct DoubleVec<NeonFloat> {\n  float64x2_t lo, hi; // lo = lanes 0,1; hi = lanes 2,3\n\n  DoubleVec() = default;\n  DoubleVec(float64x2_t l, float64x2_t h) : lo(l), hi(h) {}\n  explicit DoubleVec(double d) : lo(vdupq_n_f64(d)), hi(vdupq_n_f64(d)) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(NeonFloat f) {\n    return {vcvt_f64_f32(vget_low_f32(f.v)), vcvt_f64_f32(vget_high_f32(f.v))};\n  }\n\n  // Gather: load base[idx[lane]] for each of 4 lanes via scalar lookups.\n  static DISPENSO_INLINE DoubleVec gather(const double* base, NeonInt32 idx) {\n    int32_t i0 = vgetq_lane_s32(idx.v, 0);\n    int32_t i1 = vgetq_lane_s32(idx.v, 1);\n    int32_t i2 = vgetq_lane_s32(idx.v, 2);\n    int32_t i3 = vgetq_lane_s32(idx.v, 3);\n    float64x2_t lo_d = vsetq_lane_f64(base[i1], vdupq_n_f64(base[i0]), 1);\n    float64x2_t hi_d = vsetq_lane_f64(base[i3], vdupq_n_f64(base[i2]), 1);\n    return {lo_d, hi_d};\n  }\n\n  DISPENSO_INLINE NeonFloat to_float() const {\n    float32x2_t lo_f = vcvt_f32_f64(lo);\n    float32x2_t hi_f = vcvt_f32_f64(hi);\n    return NeonFloat{vcombine_f32(lo_f, hi_f)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return {vaddq_f64(a.lo, b.lo), vaddq_f64(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return {vsubq_f64(a.lo, b.lo), vsubq_f64(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return {vmulq_f64(a.lo, b.lo), vmulq_f64(a.hi, b.hi)};\n  }\n\n  // AArch64 always has FMA.\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n    return {vfmaq_f64(c.lo, a.lo, b.lo), vfmaq_f64(c.hi, a.hi, b.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return {\n        vminnmq_f64(vmaxnmq_f64(x.lo, low.lo), high.lo),\n        vminnmq_f64(vmaxnmq_f64(x.hi, low.hi), high.hi)};\n  }\n};\n\nDISPENSO_INLINE std::pair<DoubleVec<NeonFloat>, DoubleVec<NeonFloat>> exp2_split(\n    DoubleVec<NeonFloat> x) {\n  using DV = DoubleVec<NeonFloat>;\n  float64x2_t kShift = vdupq_n_f64(0x1.8p+52);\n\n  float64x2_t shifted_lo = vaddq_f64(x.lo, kShift);\n  float64x2_t shifted_hi = vaddq_f64(x.hi, kShift);\n\n  uint64x2_t ki_lo = vreinterpretq_u64_f64(shifted_lo);\n  uint64x2_t ki_hi = vreinterpretq_u64_f64(shifted_hi);\n\n  float64x2_t nd_lo = vsubq_f64(shifted_lo, kShift);\n  float64x2_t nd_hi = vsubq_f64(shifted_hi, kShift);\n\n  float64x2_t r_lo = vsubq_f64(x.lo, nd_lo);\n  float64x2_t r_hi = vsubq_f64(x.hi, nd_hi);\n\n  uint64x2_t kShiftBits = vdupq_n_u64(0x4338000000000000ULL);\n  uint64x2_t k1023 = vdupq_n_u64(1023);\n\n  uint64x2_t n_lo = vsubq_u64(ki_lo, kShiftBits);\n  uint64x2_t n_hi = vsubq_u64(ki_hi, kShiftBits);\n\n  float64x2_t scale_lo = vreinterpretq_f64_u64(vshlq_n_u64(vaddq_u64(n_lo, k1023), 52));\n  float64x2_t scale_hi = vreinterpretq_f64_u64(vshlq_n_u64(vaddq_u64(n_hi, k1023), 52));\n\n  return {DV{r_lo, r_hi}, DV{scale_lo, scale_hi}};\n}\n\n#endif // __aarch64__\n\n// ---------------------------------------------------------------------------\n// Highway: DoubleVec<HwyFloat> holds two Vec<Repartition<double, FloatTag>>.\n// Width adapts to the compile-time target (SSE→2×2, AVX→2×4, AVX-512→2×8).\n// ---------------------------------------------------------------------------\n#if __has_include(\"hwy/highway.h\")\n\n#include <dispenso/fast_math/float_traits_hwy.h>\n\ntemplate <>\nstruct DoubleVec<HwyFloat> {\n  using DTag = hn::Repartition<double, HwyFloatTag>;\n  using DV = hn::Vec<DTag>;\n  using ITag = hn::RebindToSigned<DTag>;\n\n  DV lo, hi; // lo = lower half lanes, hi = upper half lanes\n\n  DoubleVec() = default;\n  DoubleVec(DV l, DV h) : lo(l), hi(h) {}\n  explicit DoubleVec(double d) : lo(hn::Set(DTag{}, d)), hi(hn::Set(DTag{}, d)) {}\n\n  static DISPENSO_INLINE DoubleVec from_float(HwyFloat f) {\n    const DTag dd;\n    return {hn::PromoteLowerTo(dd, f.v), hn::PromoteUpperTo(dd, f.v)};\n  }\n\n  // Gather: load base[idx[lane]] for each lane via scalar lookups.\n  // Highway lacks a double-precision gather from int32 indices, so we\n  // extract indices and load scalars. The table is small and L1-hot.\n  static DISPENSO_INLINE DoubleVec gather(const double* base, HwyInt32 idx) {\n    const DTag dd;\n    constexpr size_t kMaxF = HWY_MAX_BYTES / sizeof(float);\n    constexpr size_t kMaxD = kMaxF / 2; // half as many double lanes\n    HWY_ALIGN int32_t ibuf[kMaxF];\n    hn::StoreU(idx.v, HwyInt32Tag{}, ibuf);\n    HWY_ALIGN double lo_buf[kMaxD];\n    HWY_ALIGN double hi_buf[kMaxD];\n    const size_t nd = hn::Lanes(dd);\n    for (size_t j = 0; j < nd; ++j) {\n      lo_buf[j] = base[ibuf[j]];\n      hi_buf[j] = base[ibuf[nd + j]];\n    }\n    return {hn::Load(dd, lo_buf), hn::Load(dd, hi_buf)};\n  }\n\n  DISPENSO_INLINE HwyFloat to_float() const {\n    const HwyFloatTag df;\n    // DemoteTo narrows each double half to a half-width float vector.\n    auto lo_f = hn::DemoteTo(hn::Rebind<float, DTag>{}, lo);\n    auto hi_f = hn::DemoteTo(hn::Rebind<float, DTag>{}, hi);\n    // Combine: lo_f and hi_f are each half-width Vec<float>; concatenate.\n    return HwyFloat{hn::Combine(df, hi_f, lo_f)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec operator+(DoubleVec a, DoubleVec b) {\n    return {hn::Add(a.lo, b.lo), hn::Add(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator-(DoubleVec a, DoubleVec b) {\n    return {hn::Sub(a.lo, b.lo), hn::Sub(a.hi, b.hi)};\n  }\n  friend DISPENSO_INLINE DoubleVec operator*(DoubleVec a, DoubleVec b) {\n    return {hn::Mul(a.lo, b.lo), hn::Mul(a.hi, b.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec fma(DoubleVec a, DoubleVec b, DoubleVec c) {\n    return {hn::MulAdd(a.lo, b.lo, c.lo), hn::MulAdd(a.hi, b.hi, c.hi)};\n  }\n\n  friend DISPENSO_INLINE DoubleVec clamp(DoubleVec x, DoubleVec low, DoubleVec high) {\n    return {hn::Min(hn::Max(x.lo, low.lo), high.lo), hn::Min(hn::Max(x.hi, low.hi), high.hi)};\n  }\n};\n\nDISPENSO_INLINE std::pair<DoubleVec<HwyFloat>, DoubleVec<HwyFloat>> exp2_split(\n    DoubleVec<HwyFloat> x) {\n  using DVH = DoubleVec<HwyFloat>;\n  using DTag = DVH::DTag;\n  using ITag = DVH::ITag;\n\n  auto kShift = hn::Set(DTag{}, 0x1.8p+52);\n  auto kShiftBits = hn::Set(ITag{}, 0x4338000000000000LL);\n  auto k1023 = hn::Set(ITag{}, int64_t{1023});\n\n  auto shifted_lo = hn::Add(x.lo, kShift);\n  auto shifted_hi = hn::Add(x.hi, kShift);\n\n  auto ki_lo = hn::BitCast(ITag{}, shifted_lo);\n  auto ki_hi = hn::BitCast(ITag{}, shifted_hi);\n\n  auto nd_lo = hn::Sub(shifted_lo, kShift);\n  auto nd_hi = hn::Sub(shifted_hi, kShift);\n\n  auto r_lo = hn::Sub(x.lo, nd_lo);\n  auto r_hi = hn::Sub(x.hi, nd_hi);\n\n  auto n_lo = hn::Sub(ki_lo, kShiftBits);\n  auto n_hi = hn::Sub(ki_hi, kShiftBits);\n\n  auto scale_lo = hn::BitCast(DTag{}, hn::ShiftLeft<52>(hn::Add(n_lo, k1023)));\n  auto scale_hi = hn::BitCast(DTag{}, hn::ShiftLeft<52>(hn::Add(n_hi, k1023)));\n\n  return {DVH{r_lo, r_hi}, DVH{scale_lo, scale_hi}};\n}\n\n#endif // __has_include(\"hwy/highway.h\")\n\n} // namespace detail\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/fast_math/detail/fast_math_impl.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <array>\n#include \"../util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\nnamespace detail {\n\n// Constants and algorithms come from \"Fast Calculation of Cube and Inverse Cube Roots Using a Magic\n// Constant and Its Implementation on Microcontrollers\" by Moroz et al.\ntemplate <typename Flt, typename AccuracyTraits>\nDISPENSO_INLINE Flt rcp_cbrt(Flt x, IntType_t<Flt> i) {\n  auto fma = FloatTraits<Flt>::fma;\n  if constexpr (AccuracyTraits::kMaxAccuracy) {\n    // Algorithm 3 step 1 + FMA quadratic correction (2 ULP, division-free Halley).\n    //\n    // Step 1 uses Algorithm 3's magic constant and tuned Newton step (~10 bits).\n    // Step 2 computes the FMA residual e = 1 - x*y^3 with single rounding (no\n    // cancellation), then applies a Sollya-optimized quadratic correction:\n    //   y *= 1 + e*(c1 + c2*e)\n    // This achieves cubic convergence (bits triple) without Halley's division,\n    // at the same op count as the previous Algorithm 5 but with better accuracy.\n    //\n    // Polynomial: fpminimax for (1-e)^(-1/3), constant=1, on [-0.005, 0.005].\n    // Relative error ~1.08e-8 (~26.5 bits).\n    constexpr float c1 = 0.3333354890346527099609375f;\n    constexpr float c2 = 0.22222582995891571044921875f;\n    i = 0x548c39cb - int_div_by_3(i);\n    Flt y = bit_cast<Flt>(i);\n    y = y * fma(-0.534850249f * x * y, y * y, 1.5015480449f);\n    Flt e = fma(x * y, -y * y, 1.0f);\n    y = y * fma(e, fma(Flt(c2), e, Flt(c1)), 1.0f);\n    return y;\n  } else {\n    // Algorithm 3 from Moroz et al. (12 ULP).\n    i = 0x548c39cb - int_div_by_3(i);\n    Flt y = bit_cast<Flt>(i);\n    y = y * fma(-0.534850249f * x * y, y * y, 1.5015480449f);\n    y = y * fma(-0.3333333333f * x * y, y * y, 1.333333985f);\n    return y;\n  }\n}\n\n// TODO: We likely will never need a double precision version of this function, but note that this\n// is definitely busted for double.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt frexpImpl(IntType_t<Flt> hx, IntType_t<Flt>* eptr) {\n  using IntT = IntType_t<Flt>;\n\n  IntT ix = 0x7fffffff & hx;\n\n  auto nonzero = hx != 0;\n  *eptr = FloatTraits<Flt>::conditional(nonzero, (ix >> 23) - 126, IntT(0));\n  return bit_cast<Flt>((hx & 0x807fffff) | 0x3f000000);\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt ldexpImpl(UintType_t<Flt> hx, IntType_t<Flt> e) {\n  auto esgn = signofi<Flt>(e);\n  e *= esgn;\n  hx += esgn * (e << 23);\n  return bit_cast<Flt>(hx);\n}\n\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt cos_pi_4(Flt x2) {\n  // Approximate cosine on [-PI/4,+PI/4], max error 0.87444 ULP.\n  // Polynomial in x²: c0 + c1*x² + c2*x⁴ + c3*x⁶ + c4*x⁸.\n  return dispenso::fast_math::hornerEval(\n      x2, 2.44677067e-5f, -1.38877297e-3f, 4.16666567e-2f, -5.00000000e-1f, 1.00000000e+0f);\n}\n\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt sin_pi_4(Flt x2, Flt x) {\n  // Approximate sine on [-PI/4,+PI/4].\n  // Sollya fpminimax(sin(x) - x, [|3,5,7,9|], [|SG...|], [-pi/4;pi/4], absolute).\n  // Odd polynomial: sin(x) = x + x³ * P(x²).\n  Flt s = dispenso::fast_math::hornerEval(\n      x2, 2.78547373e-6f, -1.98483889e-4f, 8.33336823e-3f, -1.66666672e-1f);\n  return FloatTraits<Flt>::fma(s, x * x2, x);\n}\n\n// Wider-domain sin/cos polynomials for pi-reduction (no quadrant blending needed).\n// sin(x) on [-pi/2, pi/2], degree 11 odd polynomial: sin(x) = x * P(x^2)\n// Sollya fpminimax(sin(x), [|1,3,5,7,9,11|], [|SG...|], [-pi/2;pi/2], absolute)\n// Absolute error: 3.2e-10 (31.5 bits)\ntemplate <typename Flt>\nDISPENSO_INLINE Flt sin_pi_2(Flt x2, Flt x) {\n  // Odd polynomial: sin(x) = x + x³ * P(x²).\n  Flt s = dispenso::fast_math::hornerEval(\n      x2, -0x1.ab55a8p-26f, 0x1.725326p-19f, -0x1.a0205p-13f, 0x1.11112ep-7f, -0x1.555556p-3f);\n  return FloatTraits<Flt>::fma(s, x * x2, x);\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt\nrangeReduceFloor(Flt& x, NonDeduced<Flt> rcpMod, NonDeduced<Flt> valHi, NonDeduced<Flt> valLo) {\n  auto j = floor_small(x * rcpMod); // FloatTraits<Flt>::fma(x, rcpMod, kMagic) - kMagic;\n  x = FloatTraits<Flt>::fma(j, -valHi, x);\n  x = FloatTraits<Flt>::fma(j, -valLo, x);\n  return j;\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt\nrangeReduce(Flt& x, NonDeduced<Flt> rcpMod, NonDeduced<Flt> valHi, NonDeduced<Flt> valLo) {\n  const Flt kMagic = FloatTraits<Flt>::kMagic;\n  auto j = FloatTraits<Flt>::fma(x, rcpMod, kMagic) - kMagic;\n  x = FloatTraits<Flt>::fma(j, -valHi, x);\n  x = FloatTraits<Flt>::fma(j, -valLo, x);\n  return j;\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt rangeReduce2(\n    Flt& x,\n    NonDeduced<Flt> rcpMod,\n    NonDeduced<Flt> valHi,\n    NonDeduced<Flt> valMed,\n    NonDeduced<Flt> valLo) {\n  const Flt kMagic = FloatTraits<Flt>::kMagic;\n  auto j = FloatTraits<Flt>::fma(x, rcpMod, kMagic) - kMagic;\n  x = FloatTraits<Flt>::fma(j, -valHi, x);\n  x = FloatTraits<Flt>::fma(j, -valMed, x);\n  x = FloatTraits<Flt>::fma(j, -valLo, x);\n  return j;\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt rangeReduce3(\n    Flt& x,\n    NonDeduced<Flt> rcpMod,\n    NonDeduced<Flt> valHi,\n    NonDeduced<Flt> valMedHi,\n    NonDeduced<Flt> valMedLo,\n    NonDeduced<Flt> valLo) {\n  const Flt kMagic = FloatTraits<Flt>::kMagic;\n  auto j = FloatTraits<Flt>::fma(x, rcpMod, kMagic) - kMagic;\n  x = FloatTraits<Flt>::fma(j, -valHi, x);\n  x = FloatTraits<Flt>::fma(j, -valMedHi, x);\n  x = FloatTraits<Flt>::fma(j, -valMedLo, x);\n  x = FloatTraits<Flt>::fma(j, -valLo, x);\n  return j;\n}\n\n// https://stackoverflow.com/questions/63918873/approximating-cosine-on-0-pi-using-only-single-precision-floating-point\n\n// Cosine has quadrant bias 1, sine has quadrant bias 0\ntemplate <typename Flt>\nDISPENSO_INLINE Flt sincos_pi_impl(Flt x, Flt j, int phaseShift) {\n  /* phase shift of pi/2 (one quadrant) for cosine */\n\n  auto i = convert_to_int(j) + phaseShift;\n  Flt r;\n  if constexpr (std::is_same_v<Flt, float>) { // For scalars, explicit if/else is faster to ensure\n    // we avoid computing both functions\n    if (i & 1) {\n      r = cos_pi_4(x * x);\n    } else {\n      r = sin_pi_4(x * x, x);\n    }\n  } else {\n    r = FloatTraits<Flt>::conditional((i & 1) != 0, cos_pi_4(x * x), sin_pi_4(x * x, x));\n  }\n\n  return FloatTraits<Flt>::conditional((i & 2) != 0, -r, r);\n}\n\n// Combined sin+cos computation. Always evaluates both polynomials (needed for sincos).\n// For SIMD types, evaluates both polynomials and blends per-lane.\ntemplate <typename Flt>\nDISPENSO_INLINE void sincos_pi_impl_both(Flt x, Flt j, Flt* out_sin, Flt* out_cos) {\n  auto i = convert_to_int(j);\n  auto x2 = x * x;\n  auto sv = sin_pi_4(x2, x);\n  auto cv = cos_pi_4(x2);\n\n  // For sin: quadrant i. For cos: quadrant i+1 (phase shift).\n  auto sin_use_cos = (i & 1) != 0;\n  auto cos_use_cos = ((i + 1) & 1) != 0;\n\n  Flt sr = FloatTraits<Flt>::conditional(sin_use_cos, cv, sv);\n  Flt cr = FloatTraits<Flt>::conditional(cos_use_cos, cv, sv);\n\n  *out_sin = FloatTraits<Flt>::conditional((i & 2) != 0, -sr, sr);\n  *out_cos = FloatTraits<Flt>::conditional(((i + 1) & 2) != 0, -cr, cr);\n}\n\n// Pi-reduction dispatch: each function evaluates only its own polynomial.\n// j = round(x / pi), so x_reduced in [-pi/2, pi/2].\n// sin(x) = (-1)^j * sin(x_reduced), cos(x) = (-1)^j * cos(x_reduced).\ntemplate <typename Flt>\nDISPENSO_INLINE Flt sin_pi_reduction(Flt x, Flt j) {\n  auto ji = convert_to_int(j);\n  auto x2 = x * x;\n  auto result = sin_pi_2(x2, x);\n  return FloatTraits<Flt>::conditional((ji & 1) != 0, -result, result);\n}\n\n// Cosine via offset-pi reduction (Highway-style).\n// q = 2*trunc(|x|/pi) + 1 maps cos zeros to x_r = 0. Then cos(x) = ±sin(x_r).\n// No quadrant blending: one polynomial, sign flip only.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt cos_offset_pi_reduction(Flt x_r, IntType_t<Flt> qi) {\n  auto x2 = x_r * x_r;\n  auto result = sin_pi_2(x2, x_r);\n  // (q & 2) == 0 → negate (cos starts positive at q=1).\n  return FloatTraits<Flt>::conditional((qi & 2) != 0, result, -result);\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt tan_pi_2_impl(Flt x, Flt j) {\n  auto i = convert_to_int(j);\n\n  auto x2 = x * x;\n\n  auto cv = cos_pi_4(x2);\n  auto sv = sin_pi_4(x2, x);\n\n  auto flip = (i & 1) != 0;\n  Flt r;\n  if constexpr (std::is_same_v<Flt, float>) {\n    if (flip) {\n      r = cv / sv;\n    } else {\n      r = sv / cv;\n    }\n  } else {\n    auto n = FloatTraits<Flt>::conditional(flip, cv, sv);\n    auto d = FloatTraits<Flt>::conditional(flip, sv, cv);\n    r = n / d;\n  }\n\n  auto neg = ((i ^ (i + 1)) & 2) != 0;\n  r = FloatTraits<Flt>::conditional(neg, -r, r);\n\n  return r;\n}\n\ntemplate <typename Flt, typename AccuracyTraits>\nDISPENSO_INLINE Flt asin_0_pt5(Flt x) {\n  // asin(x) = x + x * x² * P(x²), where P approximates (asin(x)-x)/x³ on [0, 0.5].\n  auto x2 = x * x;\n  Flt px;\n  if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n    // Sollya fpminimax((asin(x)-x)/x^3, [|0,2,4,6,8,10|], [|SG...|], [1b-50, 0.5]):\n    //   sup-norm error < 2^-27.\n    px = dispenso::fast_math::hornerEval(\n             x2,\n             0x1.1a258cp-5f,\n             0x1.10abf6p-6f,\n             0x1.ff9494p-6f,\n             0x1.6d4032p-5f,\n             0x1.3334c8p-4f,\n             0x1.555554p-3f) *\n        x2;\n  } else {\n    // Sollya fpminimax((asin(x)-x)/x^3, [|0,2,4,6,8|], [|SG...|], [1b-50, 0.5]):\n    //   sup-norm error < 2^-24.\n    px = dispenso::fast_math::hornerEval(\n             x2, 0x1.3926d2p-5f, 0x1.b1e3acp-6f, 0x1.70bf2ap-5f, 0x1.332688p-4f, 0x1.55555ep-3f) *\n        x2;\n  }\n  return x + x * px;\n}\n\ntemplate <typename Flt, typename AccuracyTraits>\nDISPENSO_INLINE Flt asin_pt5_1(Flt x) {\n  // asin(x) = pi/2 + sqrt(1-x) * P(x), where P approximates (asin(x)-pi/2)/sqrt(1-x)\n  // on [0.5, 1].\n  constexpr float kPi_2hi = 1.57079637050628662109375f;\n  constexpr float kPi_2lo = -4.37113900018624283e-8f;\n\n  Flt y;\n  if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n    // Sollya fpminimax((asin(x)-pi/2)/sqrt(1-x), 6, [|SG...|], [0.5, 1-1b-23]):\n    //   sup-norm error < 2^-32.\n    y = dispenso::fast_math::hornerEval(\n        x,\n        -0x1.b7070cp-11f,\n        0x1.72345p-8f,\n        -0x1.2f2922p-6f,\n        0x1.59358ep-5f,\n        -0x1.5f9f5p-4f,\n        0x1.b6199ap-3f,\n        -0x1.921b8p0f);\n  } else {\n    // Sollya fpminimax((asin(x)-pi/2)/sqrt(1-x), 5, [|SG...|], [0.5, 1-1b-23]):\n    //   sup-norm error < 2^-28.\n    y = dispenso::fast_math::hornerEval(\n        x,\n        0x1.edfaacp-10f,\n        -0x1.79d524p-7f,\n        0x1.216da6p-5f,\n        -0x1.507bb6p-4f,\n        0x1.b3ef5cp-3f,\n        -0x1.921358p0f);\n  }\n\n  // Use compensating sum for better rounding.\n  return kPi_2hi + FloatTraits<Flt>::fma(FloatTraits<Flt>::sqrt(1.0f - x), y, kPi_2lo);\n}\n\ntemplate <typename Flt, typename AccuracyTraits>\nDISPENSO_INLINE std::tuple<IntType_t<Flt>, Flt, Flt> logarithmSep(Flt& x) {\n  using IntT = IntType_t<Flt>;\n  using UintT = UintType_t<Flt>;\n  IntT xi;\n  Flt i;\n  Flt m;\n  auto fma = FloatTraits<Flt>::fma;\n\n  if constexpr (AccuracyTraits::kMaxAccuracy) {\n    auto small = x < 1.175494351e-38f;\n    x = FloatTraits<Flt>::conditional(small, x * 8388608.0f, x);\n    i = FloatTraits<Flt>::conditional(small, Flt(-23.0f), Flt(0.0f));\n\n    xi = bit_cast<IntT>(x);\n    // Use unsigned arithmetic to avoid signed overflow UB on negative inputs.\n    UintT xu = bit_cast<UintT>(x);\n    UintT e = (xu - UintT(0x3f3504f3)) & UintT(0xff800000);\n    m = bit_cast<Flt>(xu - e);\n    i = fma(Flt(bit_cast<IntT>(e)), 1.19209290e-7f, i);\n  } else {\n    // Ignore denorms, degradation behavior not that bad\n    xi = bit_cast<IntT>(x);\n    UintT xu = bit_cast<UintT>(x);\n    UintT e = (xu - UintT(0x3f3504f3)) & UintT(0xff800000);\n    m = bit_cast<Flt>(xu - e);\n    i = Flt(bit_cast<IntT>(e)) * 1.19209290e-7f;\n  }\n  return {xi, i, m};\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt logarithmBounds(Flt x, Flt y, IntType_t<Flt> xi) {\n  using IntT = IntType_t<Flt>;\n  using UintT = UintType_t<Flt>;\n  // Negative-input detection uses unsigned comparison: negative float bit\n  // patterns have the sign bit set, making them large unsigned values.  Scalar\n  // C++ promotes to unsigned implicitly, but SIMD integer comparison intrinsics\n  // are always signed, so we use UintT explicitly for the SIMD path.\n  //\n  // Condition 3 (negative detection) uses > 0x80000000u (not >= ) so that -0.0f\n  // (bit pattern 0x80000000) is excluded — IEEE 754 requires log(-0) = -inf,\n  // which is already handled by condition 1 (x == 0.0f).\n  if constexpr (std::is_same_v<Flt, float>) {\n    if (xi < 0x00800000 || xi >= 0x7f800000) {\n      int orbits = bool_apply_or_zero<int>(x == 0.0f, 0xff800000);\n      orbits |= bool_apply_or_zero<int>((xi & 0x7f800000) == 0x7f800000, xi);\n      orbits |= bool_apply_or_zero<int>(static_cast<uint32_t>(xi) > 0x80000000u, 0x7f8fffff);\n      y = orbits ? bit_cast<float>(orbits) : y;\n    }\n  } else {\n    IntT orbits = bool_apply_or_zero<IntT>(x == 0.0f, 0xff800000);\n    orbits |= bool_apply_or_zero<IntT>((xi & 0x7f800000) == 0x7f800000, xi);\n    orbits |= bool_apply_or_zero<IntT>(bit_cast<UintT>(xi) > UintT(0x80000000), 0x7f8fffff);\n    // Use a proper mask (all-ones/all-zeros) for conditional, since blendv\n    // only checks bit 31.  Raw orbits values like 0x7F800000 (+inf) have bit 31\n    // clear and would be incorrectly treated as \"false\".\n    auto hasBound = orbits != IntT(0);\n    y = FloatTraits<Flt>::conditional(hasBound, bit_cast<Flt>(orbits), y);\n  }\n  return y;\n}\n\ntemplate <typename Flt, typename AccuracyTraits>\nDISPENSO_INLINE Flt atan_poly(Flt x) {\n  // atan(x) ≈ x * P(x), where P approximates atan(x)/x on [0, 1].\n  // Horner (not Estrin): Estrin regresses atan ULP from 3 to 4 and is slower\n  // on scalar due to register pressure from the x-power tree.\n  Flt y;\n  if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n    // Sollya fpminimax(atan(x)/x, 11, [|SG...|], [1b-50, 1]):\n    //   sup-norm error < 2^-31.\n    y = dispenso::fast_math::hornerEval(\n        x,\n        -0x1.1592cap-6f,\n        0x1.a09c1cp-4f,\n        -0x1.f68112p-3f,\n        0x1.150f26p-2f,\n        -0x1.e2e56p-5f,\n        -0x1.0e262ep-3f,\n        -0x1.d8f3p-15f,\n        0x1.98c9aap-3f,\n        0x1.352e9p-14f,\n        -0x1.5556b2p-2f,\n        0x1.f2bd6p-24f,\n        0x1p0f);\n  } else {\n    // Sollya fpminimax(atan(x)/x, 9, [|SG...|], [1b-50, 1]):\n    //   sup-norm error < 2^-26.\n    y = dispenso::fast_math::hornerEval(\n        x,\n        0x1.1f76cap-6f,\n        -0x1.cc3324p-4f,\n        0x1.252662p-2f,\n        -0x1.530ee2p-2f,\n        0x1.2ca298p-4f,\n        0x1.76789ap-3f,\n        0x1.29d66ep-9f,\n        -0x1.557c3cp-2f,\n        0x1.c39d04p-19f,\n        0x1p0f);\n  }\n  return y * x;\n}\n\n} // namespace detail\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/fast_math/fast_math.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * EXPERIMENTAL — This sublibrary is under active development.\n * The API is unstable and subject to breaking changes without notice.\n * Do not depend on it in production code.\n */\n\n#pragma once\n\n#include <array>\n\nnamespace dispenso {\nnamespace fast_math {\n\nstruct DefaultAccuracyTraits {\n  // Check for out-of-range, NaN, Inf inputs and ensure outputs match std.  Note that functions may\n  // still provide correct values out of bounds, but if this is false, they are not required to.\n  static constexpr bool kBoundsValues = false;\n  // Try to get the lowest possible errors to match std.\n  static constexpr bool kMaxAccuracy = false;\n};\n\nstruct MaxAccuracyTraits {\n  // Check for out-of-range, NaN, Inf inputs and ensure outputs match std\n  static constexpr bool kBoundsValues = true;\n  // Try to get the lowest possible errors to match std.\n  static constexpr bool kMaxAccuracy = true;\n};\n\n} // namespace fast_math\n} // namespace dispenso\n\n#include \"detail/double_promote.h\"\n#include \"detail/fast_math_impl.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nnamespace detail {\n\n// AccuracyTraits adapter for internal pow use: always uses best polynomial,\n// inherits kBoundsValues from the outer traits.\ntemplate <typename AccuracyTraits>\nstruct PowInternalTraits {\n  static constexpr bool kMaxAccuracy = true;\n  static constexpr bool kBoundsValues = AccuracyTraits::kBoundsValues;\n};\n\n// Scalar integer parity check on float bits.\n// Returns 0 if y is not an integer, 1 if even integer, 2 if odd integer.\n// Works regardless of sign bit (sign is masked off from exponent field).\n// Branching version — used inside the rare negative-x path.\nDISPENSO_INLINE int32_t checkint(uint32_t iy) {\n  int32_t e = static_cast<int32_t>(iy >> 23) & 0xff;\n  if (e < 127)\n    return 0; // |y| < 1 → not integer (includes 0, subnormals)\n  if (e > 127 + 23)\n    return 1; // |y| >= 2^24 → ULP ≥ 2, only even integers representable\n  // 127 <= e <= 150: check mantissa bits below the integer point.\n  uint32_t shift = static_cast<uint32_t>(127 + 23 - e);\n  if (iy & ((1u << shift) - 1u))\n    return 0; // fractional mantissa bits → not integer\n  if (iy & (1u << shift))\n    return 2; // lowest integer bit set → odd\n  return 1; // even integer\n}\n\n// Branchless integer parity check for the scalar non-bounds path.\n// Returns 0 if not integer, 1 if even integer, 2 if odd integer.\n// For the non-bounds default path, we want to avoid branches on the hot path.\n// The negative-x case is rare, but mixed-sign workloads benefit from branchless.\nDISPENSO_INLINE int32_t checkint_branchless(uint32_t iy) {\n  int32_t e = static_cast<int32_t>(iy >> 23) & 0xff;\n  // Clamp shift to [0, 31] to avoid UB from shifting >= 32. When e < 127\n  // (|y| < 1, not integer), the clamped shift reads a garbage bit, but\n  // is_int below is false so the garbage is never used.\n  uint32_t shift = static_cast<uint32_t>(127 + 23 - e) & 31u;\n  uint32_t has_frac = iy & ((1u << shift) - 1u);\n  uint32_t odd_bit = (iy >> shift) & 1u;\n  // is_int: e >= 127 and no fractional bits (or e > 150, always integer).\n  // For e > 150: shift would be negative (clamped to garbage), but we force result = 1.\n  int32_t is_int = (e >= 127) & (has_frac == 0);\n  int32_t is_large = (e > 127 + 23); // always even\n  // Result: 0 if not int, 1 if even int, 2 if odd int.\n  // odd_bit is meaningful only when is_int && !is_large.\n  return is_int + (is_int & static_cast<int32_t>(odd_bit) & ~is_large);\n}\n\n// Scalar double-precision pow core: exp2(y * log2(|x|)) entirely in double.\n// Float inputs/output, double internal arithmetic.\n//\n// log2: 16-entry table of {1/c, log2(c)} eliminates division. Degree-4\n//   polynomial (Sollya fpminimax) approximates log2(1+r)/r with pipelined\n//   evaluation. Table centers at OFF + i*2^19 + 2^18, max |r| < 0.0297.\n// exp2: 32-entry table of 2^(k/32) stored as uint64 with pre-subtracted\n//   exponent bits. Degree-3 polynomial (Sollya fpminimax) on [-1/64, 1/64].\n//\n// Total: ~8 double muls + ~5 double adds in two short parallel chains.\n// Achieves <1 ULP for float output.\n\n// log2 table: 16 entries, each {1/c, log2(c)} where c is the center of\n// the ith subinterval of [OFF, 2*OFF] (OFF = 0x3f330000).\nstruct PowLog2Entry {\n  double invc;\n  double logc;\n};\n\n// EXP2F_TABLE_BITS = 5 → 32 entries.\n// tab[i] = uint64(2^(i/32)) - (i << (52-5)).\n// To reconstruct 2^(k/32): double(tab[k%32] + (k << 47)).\nconstexpr uint64_t kPowExp2Tab[32] = {\n    0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51,\n    0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1,\n    0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d,\n    0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585,\n    0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13,\n    0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d,\n    0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069,\n    0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540,\n};\n\nconstexpr PowLog2Entry kPowLog2Tab[16] = {\n    {0x1.661ec6a5122f9p+0, -0x1.efec61b011f85p-2}, // i=0,  c=0.71484375\n    {0x1.571ed3c506b3ap+0, -0x1.b0b67f4f46810p-2}, // i=1,  c=0.74609375\n    {0x1.49539e3b2d067p+0, -0x1.7418acebbf18fp-2}, // i=2,  c=0.77734375\n    {0x1.3c995a47babe7p+0, -0x1.39de8e1559f6fp-2}, // i=3,  c=0.80859375\n    {0x1.30d190130d190p+0, -0x1.01d9bbcfa61d4p-2}, // i=4,  c=0.83984375\n    {0x1.25e22708092f1p+0, -0x1.97c1cb13c7ec1p-3}, // i=5,  c=0.87109375\n    {0x1.1bb4a4046ed29p+0, -0x1.2f9e32d5bfdd1p-3}, // i=6,  c=0.90234375\n    {0x1.12358e75d3033p+0, -0x1.960caf9abb7cap-4}, // i=7,  c=0.93359375\n    {0x1.0953f39010954p+0, -0x1.a6f9c377dd31bp-5}, // i=8,  c=0.96484375\n    {0x1p+0, 0x0p+0}, // i=9,  c=1.0 (exact)\n    {0x1.e573ac901e574p-1, 0x1.3aa2fdd27f1c3p-4}, // i=10, c=1.05468750\n    {0x1.ca4b3055ee191p-1, 0x1.476a9f983f74dp-3}, // i=11, c=1.11718750\n    {0x1.b2036406c80d9p-1, 0x1.e840be74e6a4dp-3}, // i=12, c=1.17968750\n    {0x1.9c2d14ee4a102p-1, 0x1.406463b1b0449p-2}, // i=13, c=1.24218750\n    {0x1.886e5f0abb04ap-1, 0x1.88e9c72e0b226p-2}, // i=14, c=1.30468750\n    {0x1.767dce434a9b1p-1, 0x1.ce0a4923a587dp-2}, // i=15, c=1.36718750\n};\n\n// log2(1+r)/r polynomial coefficients (degree 4, Sollya fpminimax).\n// Relative error < 2^-32 on |r| < 0.0297.\nconstexpr double kPowLog2Poly[5] = {\n    0x1.27bc533354f16p-2, // P[0]: r^4 coeff\n    -0x1.719a02b5d4c08p-2, // P[1]: r^3 coeff\n    0x1.ec70982733e8fp-2, // P[2]: r^2 coeff\n    -0x1.7154745c0af07p-1, // P[3]: r   coeff (approx -1/(2*ln2))\n    0x1.71547652bc3ep0, // P[4]: r^0 coeff (approx 1/ln2)\n};\n\n// exp2 polynomial coefficients (degree 3 on [-1/64, 1/64], Sollya fpminimax).\n// Relative error < 2^-27 on (2^r - 1)/r.\nconstexpr double kPowExp2Poly[3] = {\n    0x1.c6b08d7047f43p-5, // C[0]: r^2 coeff\n    0x1.ebfccc582d012p-3, // C[1]: r   coeff\n    0x1.62e42fefe5286p-1, // C[2]: r^0 coeff (approx ln2)\n};\n\nDISPENSO_INLINE float pow_double_core(float ax, float y) {\n  constexpr uint32_t kOff = 0x3f330000;\n\n  // --- log2 ---\n  uint32_t ix = bit_cast<uint32_t>(ax);\n  uint32_t tmp = ix - kOff;\n  int32_t i = (tmp >> (23 - 4)) & 15; // table index\n  uint32_t top = tmp & 0xff800000u;\n  uint32_t iz = ix - top;\n  int32_t k = static_cast<int32_t>(top) >> 23; // exponent (arithmetic shift)\n  double invc = kPowLog2Tab[i].invc;\n  double logc = kPowLog2Tab[i].logc;\n  double z = static_cast<double>(bit_cast<float>(iz));\n\n  // log2(x) = log1p(z/c - 1)/ln2 + log2(c) + k\n  double r = z * invc - 1.0;\n  double y0 = logc + static_cast<double>(k);\n\n  // Pipelined polynomial: two parallel chains merged via r4.\n  double r2 = r * r;\n  double p0 = kPowLog2Poly[0] * r + kPowLog2Poly[1];\n  double p1 = kPowLog2Poly[2] * r + kPowLog2Poly[3];\n  double r4 = r2 * r2;\n  double p2 = kPowLog2Poly[4] * r + y0;\n  p2 = p1 * r2 + p2;\n  double logx = p0 * r4 + p2;\n\n  // --- y * log2(x) ---\n  double ylogx = static_cast<double>(y) * logx;\n\n  // Overflow/underflow check.\n  // Check if |ylogx| >= 126 using exponent bits.\n  uint64_t ylogx_bits = bit_cast<uint64_t>(ylogx);\n  if ((ylogx_bits >> 47 & 0xffff) >= (bit_cast<uint64_t>(126.0) >> 47)) {\n    if (ylogx > 0x1.fffffffd1d571p+6) {\n      return std::numeric_limits<float>::infinity();\n    }\n    if (ylogx <= -150.0) {\n      return 0.0f;\n    }\n  }\n\n  // --- exp2 ---\n  // x = k/N + r with r in [-1/(2N), 1/(2N)], N=32.\n  constexpr double kShift = 0x1.8p+52 / 32.0; // magic for round-to-nearest\n  double kd = ylogx + kShift;\n  uint64_t ki = bit_cast<uint64_t>(kd);\n  kd -= kShift; // k/N, rounded\n  double rd = ylogx - kd;\n\n  // exp2(x) = 2^(k/N) * (C0*r^3 + C1*r^2 + C2*r + 1)\n  //         = s * poly(r)\n  uint64_t t = kPowExp2Tab[ki & 31];\n  t += ki << (52 - 5); // add exponent\n  double s = bit_cast<double>(t);\n\n  double r2e = rd * rd;\n  double pe = kPowExp2Poly[0] * rd + kPowExp2Poly[1];\n  double qe = kPowExp2Poly[2] * rd + 1.0;\n  qe = pe * r2e + qe;\n  return static_cast<float>(qe * s);\n}\n\n// Hybrid double-precision pow core: table-assisted log2 + tableless exp2.\n// Float inputs/output, double internal arithmetic via DoubleVec<Flt>.\n//\n// log2: SIMD range reduction (float/uint32) extracts a 4-bit table index per\n//   lane. Scalar lookups fetch {1/c, log2(c)} from the 16-entry table, packed\n//   into DoubleVec. The table narrows |r| to <0.03, enabling a degree-4\n//   polynomial (vs degree-10 tableless). 8 scalar loads total (4 lanes × 2\n//   values), always L1-hot (256 bytes).\n// exp2: tableless degree-5 polynomial via exp2_split (same as poly core).\n//\n// Works for both scalar (Flt=float) and SIMD (Flt=SseFloat, etc.).\ntemplate <typename Flt>\nDISPENSO_INLINE Flt pow_double_hybrid_core(Flt ax, Flt y) {\n  using DV = DoubleVec<Flt>;\n  using IntT = IntType_t<Flt>;\n  using UintT = UintType_t<Flt>;\n\n  // --- Range reduction (SIMD, same as pow_double_core) ---\n  // Note: does NOT handle subnormal ax (ix < 0x00800000). Callers must\n  // catch subnormals in is_special and fall back to pow_double_poly_core.\n  constexpr uint32_t kOff = 0x3f330000;\n  UintT ix = bit_cast<UintT>(ax);\n  UintT tmp = ix - UintT(kOff);\n  IntT i = (bit_cast<IntT>(tmp) >> 19) & IntT(15); // 4-bit table index\n  UintT top = tmp & UintT(0xff800000u);\n  UintT iz = ix - top;\n  IntT k = bit_cast<IntT>(top) >> 23; // exponent (arithmetic shift)\n\n  // --- Table lookups: 4 lanes × {invc, logc} = 8 scalar loads ---\n  // Table is 16 × {double, double} = 256 bytes, stride 2 doubles per entry.\n  const double* tab = reinterpret_cast<const double*>(kPowLog2Tab);\n  IntT i2 = i + i; // stride: 2 doubles per entry\n  DV invc = DV::gather(tab, i2); // tab[2*i + 0] = invc\n  DV logc = DV::gather(tab, i2 + IntT(1)); // tab[2*i + 1] = logc\n\n  // --- log2 in double ---\n  DV z = DV::from_float(bit_cast<Flt>(iz));\n  DV r = z * invc - DV(1.0);\n  DV y0 = logc + DV::from_float(Flt(k));\n\n  // Degree-4 Horner for log2 (chain too short for Estrin benefit).\n  // log2(x) = y0 + r * P(r), |r| < 0.03.\n  DV p(kPowLog2Poly[0]);\n  p = fma(p, r, DV(kPowLog2Poly[1]));\n  p = fma(p, r, DV(kPowLog2Poly[2]));\n  p = fma(p, r, DV(kPowLog2Poly[3]));\n  p = fma(p, r, DV(kPowLog2Poly[4]));\n  DV logx = fma(p, r, y0);\n\n  // --- y * log2(x) ---\n  DV ylogx = DV::from_float(y) * logx;\n\n  // Clamp to valid double exponent range.\n  ylogx = clamp(ylogx, DV(-1022.0), DV(1023.0));\n\n  // --- Tableless exp2 in double ---\n  auto [re, scale] = exp2_split(ylogx);\n\n  // Degree-5 Horner for exp2 (chain too short for Estrin benefit).\n  DV q(0x1.4308fabc18decp-13);\n  q = fma(q, re, DV(0x1.5f07b4611e454p-10));\n  q = fma(q, re, DV(0x1.3b2b9fbd8970fp-7));\n  q = fma(q, re, DV(0x1.c6af6e92be375p-5));\n  q = fma(q, re, DV(0x1.ebfbdec29c82ap-3));\n  q = fma(q, re, DV(0x1.62e4302eeb44dp-1));\n\n  DV result = fma(scale, re * q, scale);\n  return result.to_float();\n}\n\n// Tableless double-precision pow core: exp2(y * log2(|x|)) entirely in double.\n// Float inputs/output, double internal arithmetic via DoubleVec<Flt>.\n//\n// log2: Uses logarithmSep range reduction (float/uint32) to get exponent i and\n//   mantissa m in [sqrt(0.5), sqrt(2)]. Then t = (double)m - 1.0 (exact in\n//   double) and log2(1+t) is evaluated as t * P(t) where P is a degree-10\n//   Sollya fpminimax polynomial (~30 bits).\n//   No tables, no division, no error tracking.\n// exp2: Tableless double-precision polynomial. Range reduce to integer n and\n//   fractional r ∈ [-0.5, 0.5], then 2^x = 2^n * (1 + r*Q(r)) where Q is a\n//   degree-5 Sollya fpminimax polynomial (~27 bits). No tables.\n//\n// Works for both scalar (Flt=float) and SIMD (Flt=SseFloat, etc.).\ntemplate <typename Flt>\nDISPENSO_INLINE Flt pow_double_poly_core(Flt ax, Flt y) {\n  using DV = DoubleVec<Flt>;\n\n  // --- Range reduction (float/uint32) ---\n  // logarithmSep gives us exponent i and mantissa m in [sqrt(0.5), sqrt(2)].\n  auto [xi, i_f, m] = logarithmSep<Flt, MaxAccuracyTraits>(ax);\n\n  // --- Widen to double BEFORE subtraction ---\n  // m - 1 in float loses ~17 bits when m ≈ 1 (catastrophic cancellation).\n  // In double, (double)m - 1.0 is exact since every float is exactly\n  // representable in double, and the result fits in 24 mantissa bits.\n  DV t = DV::from_float(m) - DV(1.0);\n  DV i_d = DV::from_float(i_f);\n\n  // --- Double polynomial: log2(1+t) = t * P(t), degree 10 (Estrin) ---\n  // Sollya fpminimax on [-0.293, 0.414], double precision.\n  // Sup-norm error: 1.10e-9 (~30 bits).\n  // Estrin's scheme evaluates independent sub-polynomials in parallel,\n  // reducing latency vs Horner by exploiting ILP (multiple independent FMAs\n  // at each level feed both FMA ports simultaneously).\n  // P(t) = (c0+c1*t) + t²*(c2+c3*t) + t⁴*(c4+c5*t) + t⁶*(c6+c7*t)\n  //       + t⁸*(c8+c9*t+c10*t²)\n  //\n  // Level 0: t², and five independent coefficient pairs.\n  DV t2 = t * t;\n  DV p01 = fma(DV(-0x1.7154762acdfffp-1), t, DV(0x1.71547656a2495p+0));\n  DV p23 = fma(DV(-0x1.71548ef022a84p-2), t, DV(0x1.ec707f060e35ep-2));\n  DV p45 = fma(DV(-0x1.ec7a94d1207adp-3), t, DV(0x1.278083c622fbcp-2));\n  DV p67 = fma(DV(-0x1.6e5f6f8760a8ap-3), t, DV(0x1.a3ee210f50f0fp-3));\n  DV p89 = fma(DV(-0x1.5a6abc244ec79p-3), t, DV(0x1.60552656955f2p-3));\n  // Level 1: t⁴, combine pairs with t².\n  DV t4 = t2 * t2;\n  DV q03 = fma(p23, t2, p01);\n  DV q47 = fma(p67, t2, p45);\n  DV q8A = fma(DV(0x1.8e0e8c535162ap-4), t2, p89); // c10*t² + (c8+c9*t)\n  // Level 2: t⁸, combine quads with t⁴.\n  DV t8 = t4 * t4;\n  DV r07 = fma(q47, t4, q03);\n  // Level 3: final combination.\n  DV p = fma(q8A, t8, r07);\n\n  // log2(1+t) = t * P(t); log2(x) = i + log2(m)\n  DV log2x = i_d + t * p;\n\n  // --- y * log2(x) ---\n  DV ylogx = DV::from_float(y) * log2x;\n\n  // Clamp to valid double exponent range [-1022, 1023].\n  // This prevents invalid bit patterns in exp2_split while preserving\n  // correct float narrowing: 2^(-1022) → 0.0f, 2^1023 → inf.\n  ylogx = clamp(ylogx, DV(-1022.0), DV(1023.0));\n\n  // --- Tableless exp2 in double ---\n  auto [r, scale] = exp2_split(ylogx);\n\n  // 2^r = 1 + r * Q(r), degree-5 Sollya fpminimax on [-0.5, 0.5].\n  // Q(r) ≈ (2^r - 1)/r. Sup-norm error: 8.88e-9 (~27 bits).\n  DV q(0x1.4308fabc18decp-13); // e5\n  q = fma(q, r, DV(0x1.5f07b4611e454p-10)); // e4\n  q = fma(q, r, DV(0x1.3b2b9fbd8970fp-7)); // e3\n  q = fma(q, r, DV(0x1.c6af6e92be375p-5)); // e2\n  q = fma(q, r, DV(0x1.ebfbdec29c82ap-3)); // e1\n  q = fma(q, r, DV(0x1.62e4302eeb44dp-1)); // e0\n\n  // 2^ylogx = scale * (1 + r * q) = scale + scale * r * q\n  DV result = fma(scale, r * q, scale);\n  return result.to_float();\n}\n\n// --- Scalar pow IEEE 754 special-case helpers ---\n\n// Handle y = 0, inf, or NaN for scalar pow bounds path.\n// Returns true if the result is determined (stored in *out).\n//\n// Bit tricks used throughout:\n//   2u * val          — left-shifts by 1, discarding the sign bit. This maps\n//                       ±0 to 0, ±inf to 0xFF000000, and NaN to > 0xFF000000.\n//   2u * val - 1u     — maps ±0 to UINT_MAX (wraps), normal floats to a\n//                       positive range, and inf/NaN to >= 0xFF000000 - 1.\n//                       So \"2u*val - 1u >= 2u*0x7f800000u - 1u\" tests whether\n//                       val is zero, inf, or NaN in one branch-free comparison.\n//   ix & 0x7FFFFFFFu  — clears the sign bit, giving |x| as raw bits.\nDISPENSO_INLINE bool pow_scalar_y_special(float x, float y, uint32_t ix, uint32_t iy, float* out) {\n  if (2u * iy == 0u) {\n    *out = 1.0f;\n    return true; // pow(x, ±0) = 1\n  }\n  if (ix == 0x3f800000u) {\n    *out = 1.0f;\n    return true; // pow(1, y) = 1 even for NaN y\n  }\n  // Either x or y is NaN → propagate via x + y (IEEE 754 NaN arithmetic).\n  if (2u * (ix & 0x7fffffffu) > 2u * 0x7f800000u || 2u * iy > 2u * 0x7f800000u) {\n    *out = x + y;\n    return true;\n  }\n  // |x| == 1 (either +1 or -1) and y is ±inf → result is 1.\n  if (2u * (ix & 0x7fffffffu) == 2u * 0x3f800000u) {\n    *out = 1.0f;\n    return true;\n  }\n  // y is ±inf (NaN cases handled above). Result is 0 or +inf depending on\n  // whether |x| < 1 and the sign of y:\n  //   |x| < 1, y = +inf → 0    |x| > 1, y = +inf → +inf\n  //   |x| < 1, y = -inf → +inf |x| > 1, y = -inf → 0\n  if ((2u * (ix & 0x7fffffffu) < 2u * 0x3f800000u) == !(iy & 0x80000000u)) {\n    *out = 0.0f;\n    return true;\n  }\n  *out = y * y; // +inf (y*y overflows to +inf for finite y, identity for ±inf)\n  return true;\n}\n\n// Handle negative/zero/inf/subnormal x for scalar pow bounds path.\n// Called when x is outside the normal positive range (the fast-path condition\n// in the caller already filtered normal positive x). Returns true if the\n// result is determined (stored in *out). Otherwise adjusts ix (to |x|, with\n// subnormals normalized) and sign_bias for the core computation.\nDISPENSO_INLINE bool\npow_scalar_x_special(uint32_t& ix, uint32_t iy, uint32_t& sign_bias, float* out) {\n  if (ix & 0x80000000u) {\n    // Negative x: check integer parity of y to determine sign of result.\n    // checkint returns: 0 = not integer, 1 = even integer, 2 = odd integer.\n    int32_t yint = checkint(iy);\n    if (yint == 2)\n      sign_bias = 0x80000000u; // odd integer y → negate final result\n    ix &= 0x7fffffffu; // work with |x| from here\n    if (ix == 0 || ix == 0x7f800000u) {\n      // -0 or -inf: |x|^2 maps 0→0 and inf→inf. Then apply sign and\n      // reciprocal (negative y inverts: pow(-0, -3) = -inf).\n      float x2 = bit_cast<float>(ix) * bit_cast<float>(ix);\n      if (iy & 0x80000000u)\n        x2 = 1.0f / x2;\n      *out = bit_cast<float>(bit_cast<uint32_t>(x2) ^ sign_bias);\n      return true;\n    }\n    if (yint == 0) {\n      *out = std::numeric_limits<float>::quiet_NaN(); // neg ^ non-integer = NaN\n      return true;\n    }\n    // Negative finite nonzero x with integer y: fall through to core with |x|.\n  }\n  // Test for +0 or +inf. \"2u*ix - 1u >= 2u*0x7f800000u - 1u\" is true when\n  // ix is 0 (wraps to UINT_MAX) or >= 0x7f800000 (inf/NaN, but NaN was\n  // already handled by the caller's y-special path).\n  if (2u * ix - 1u >= 2u * 0x7f800000u - 1u) {\n    float x2 = bit_cast<float>(ix) * bit_cast<float>(ix);\n    if (iy & 0x80000000u)\n      x2 = 1.0f / x2;\n    *out = x2;\n    return true;\n  }\n  if (ix < 0x00800000u) {\n    // Subnormal x: scale by 2^23 to normalize, then subtract 23 from the\n    // biased exponent so the log2 core sees the correct value.\n    ix = bit_cast<uint32_t>(bit_cast<float>(ix) * 0x1p23f);\n    ix -= 23u << 23;\n  }\n  return false; // Fall through to core computation with adjusted ix.\n}\n\n// SIMD pow fixup for special inputs (zero, subnormal, inf, NaN).\n// The double-precision cores produce garbage for these because logarithmSep's\n// range reduction (exponent extraction via integer subtract) is undefined for\n// zero/inf/NaN bit patterns. This cold-path fixup corrects only the affected\n// lanes; the branch is almost never taken for normal workloads.\ntemplate <typename Flt>\nDISPENSO_INLINE void pow_simd_special_fixup(Flt ax, Flt y, Flt& r) {\n  using IntT = IntType_t<Flt>;\n  using UintT = UintType_t<Flt>;\n  IntT axi = bit_cast<IntT>(ax);\n  // Detect special lanes: subnormal (exponent field 0, mantissa nonzero),\n  // zero (all bits 0), inf (0x7F800000), NaN (> 0x7F800000).\n  // nonnormal() checks exponent == 0xFF (inf/NaN). Combined with < 0x00800000\n  // (subnormal/zero), this covers all non-normal inputs.\n  auto is_special = (axi < IntT(0x00800000)) | nonnormal<Flt>(axi);\n  if (DISPENSO_EXPECT(any_true(is_special), 0)) {\n    // Subnormals: the hybrid core's range reduction (ix - kOff) can't handle\n    // exponent-0 bit patterns. Recompute these lanes via poly core, whose\n    // logarithmSep prescales subnormals by 2^23 before extraction.\n    auto is_subnorm = (axi > IntT(0)) & (axi < IntT(0x00800000));\n    if (any_true(is_subnorm)) {\n      Flt r_sub = pow_double_poly_core(ax, y);\n      r = FloatTraits<Flt>::conditional(is_subnorm, r_sub, r);\n    }\n    // Zero/inf/NaN lanes: use an integer trick that swaps 0↔inf in one op.\n    // IEEE 754 bit layout: 0 = 0x00000000, +inf = 0x7F800000.\n    // 0x7F800000 - 0x00000000 = 0x7F800000 (+inf)  → pow(0, pos) = 0, pow(0, neg) = inf\n    // 0x7F800000 - 0x7F800000 = 0x00000000 (0)     → pow(inf, pos) = inf, pow(inf, neg) = 0\n    // 0x7F800000 - (NaN bits) wraps negative, which reinterprets as NaN\n    // (sign bit irrelevant for NaN). So:\n    //   y > 0 → result = ax (0 stays 0, inf stays inf)\n    //   y < 0 → result = flipped (0↔inf swap)\n    //   NaN   → stays NaN either way\n    auto is_zinf = (axi == IntT(0)) | nonnormal<Flt>(axi);\n    UintT ax_bits = bit_cast<UintT>(ax);\n    Flt flipped = bit_cast<Flt>(UintT(0x7F800000u) - ax_bits);\n    Flt special_r = FloatTraits<Flt>::conditional(y < 0.0f, flipped, ax);\n    r = FloatTraits<Flt>::conditional(is_zinf, special_r, r);\n  }\n}\n\n// Scalar-exponent fast paths: exact results for common y values and\n// binary squaring for small integer exponents. Sets y_is_int and y_is_odd\n// as output for the caller's sign-handling path when returning false.\ntemplate <typename Flt>\nDISPENSO_INLINE bool\npow_scalar_y_fast_path(Flt x, float y, bool& y_is_int, bool& y_is_odd, Flt& out) {\n  using UintT = UintType_t<Flt>;\n  if (y == 0.0f) {\n    out = Flt(1.0f);\n    return true;\n  }\n  if (y == 1.0f) {\n    out = x;\n    return true;\n  }\n  if (y == -1.0f) {\n    out = Flt(1.0f) / x;\n    return true;\n  }\n  if (y == 0.5f) {\n    constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();\n    auto negx = x < 0.0f;\n    out = FloatTraits<Flt>::conditional(negx, Flt(kNaN), FloatTraits<Flt>::sqrt(x));\n    return true;\n  }\n  if (y == 2.0f) {\n    out = x * x;\n    return true;\n  }\n\n  float ay = std::fabs(y);\n  y_is_int = (std::floor(y) == y);\n  y_is_odd = y_is_int && (std::fmod(ay, 2.0f) == 1.0f);\n\n  if (y_is_int && ay < 64.0f) {\n    // Binary squaring with uniform SIMD multiplies.\n    int32_t n = static_cast<int32_t>(ay);\n    Flt result(1.0f);\n    Flt base = fabs(x);\n    while (n > 0) {\n      if (n & 1)\n        result = result * base;\n      base = base * base;\n      n >>= 1;\n    }\n    if (y < 0.0f)\n      result = Flt(1.0f) / result;\n    if (y_is_odd) {\n      UintT xsign = bit_cast<UintT>(x) & UintT(0x80000000u);\n      result = bit_cast<Flt>(bit_cast<UintT>(result) ^ xsign);\n    }\n    out = result;\n    return true;\n  }\n  return false;\n}\n\n} // namespace detail\n\n// Compile-time check that Flt is a supported type: float, a SIMD float wrapper,\n// or a raw intrinsic type that maps to one via SimdTypeFor.\ntemplate <typename Flt>\nconstexpr void assert_float_type() {\n  // For raw intrinsics (__m128 etc.), SimdType_t maps to the wrapper (SseFloat etc.).\n  // For wrappers and float, SimdType_t is identity. Check that FloatTraits exists\n  // by verifying the kOne constant is present (only defined for float-based types).\n  static_assert(\n      FloatTraits<SimdType_t<Flt>>::kOne == 0x3f800000,\n      \"fast_math only supports float and float-based SIMD types (SseFloat, AvxFloat, etc.)\");\n}\n\n/**\n * @brief Hardware-delegated square root.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored; result is always 0 ULP.\n * @param x Input value.\n * @return Square root of @p x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt sqrt(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return FloatTraits<SimdType_t<Flt>>::sqrt(SimdType_t<Flt>(x)).v;\n  } else {\n    return std::sqrt(x);\n  }\n}\n\n/**\n * @brief Cube root approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 12 ULP, MaxAccuracy: 3 ULP.\n *   kBoundsValues: returns input for inf/NaN/zero.\n * @param x Input value (all float domain, including denormals).\n * @return Cube root of @p x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt cbrt(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    // Raw intrinsic type (__m128, Vec512<float>, etc.) — forward to wrapper.\n    return cbrt<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar path: branchless for the normal case.\n    // Denormals get prescale=2^24, postscale=1/256 (cmov).\n    // Zero is zeroed via AND mask (no blend).\n    uint32_t ui = bit_cast<uint32_t>(x);\n    uint32_t usgn = ui & 0x80000000u;\n    uint32_t uabs = ui & 0x7fffffffu;\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      if (DISPENSO_EXPECT((uabs & 0x7f800000u) == 0x7f800000u, 0)) {\n        return x; // inf/NaN\n      }\n      if (DISPENSO_EXPECT(uabs == 0u, 0)) {\n        return x; // ±0 (preserves -0)\n      }\n    }\n\n    // expZero covers both zero and denormal; zero is handled by AND mask below.\n    bool expZero = (uabs & 0x7f800000u) == 0u;\n    float prescale = expZero ? 16777216.0f : 1.0f;\n    float postscale = expZero ? (1.0f / 256.0f) : 1.0f;\n\n    float absX = bit_cast<float>(uabs) * prescale;\n    int32_t iScaled = static_cast<int32_t>(bit_cast<uint32_t>(absX));\n    float sgnx = bit_cast<float>(usgn | 0x3f800000u);\n    float result = sgnx / detail::rcp_cbrt<float, AccuracyTraits>(absX, iScaled);\n    result *= postscale;\n\n    // Zero mask: AND zeros out result for zero input, OR sign bit back in\n    // so that cbrt(-0) = -0.\n    uint32_t zeroMask = 0u - static_cast<uint32_t>(uabs != 0u);\n    return bit_cast<float>((bit_cast<uint32_t>(result) & zeroMask) | usgn);\n  } else {\n    // SIMD wrapper path: prescale/postscale multipliers + AND mask for zero.\n    using IntT = IntType_t<Flt>;\n    IntT i = bit_cast<IntT>(x);\n    IntT isgn = i & 0x80000000;\n    i &= 0x7fffffff;\n\n    // expZero covers both zero and denormal.\n    auto expZero = (i & 0x7f800000) == 0;\n\n    Flt prescale = FloatTraits<Flt>::conditional(expZero, Flt(16777216.0f), Flt(1.0f));\n    Flt postscale = FloatTraits<Flt>::conditional(expZero, Flt(1.0f / 256.0f), Flt(1.0f));\n\n    Flt absX = bit_cast<Flt>(i) * prescale;\n    IntT iScaled = bit_cast<IntT>(absX);\n\n    Flt sgnx = bit_cast<Flt>(isgn | FloatTraits<Flt>::kOne);\n    Flt result = sgnx / detail::rcp_cbrt<Flt, AccuracyTraits>(absX, iScaled);\n    result = result * postscale;\n\n    // Zero: AND mask zeroes result, OR sign bit back so cbrt(-0) = -0.\n    auto zeroMask = bool_as_mask<IntT>(i != 0);\n    result = bit_cast<Flt>((bit_cast<IntT>(result) & zeroMask) | isgn);\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      return FloatTraits<Flt>::conditional(nonnormal<Flt>(iScaled), x, result);\n    }\n    return result;\n  }\n}\n\n/**\n * @brief Decompose a float into mantissa and exponent (bit-accurate for normals).\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored; result is always bit-accurate.\n * @param x Input value.\n * @param eptr Pointer to receive the exponent.\n * @return Mantissa in [0.5, 1) for normal values. Returns @p x unchanged for\n *   inf/NaN/zero/subnormal. Subnormals are passed through with *eptr = 0\n *   rather than normalized into [0.5, 1) as std::frexp does. This means the\n *   mantissa contract is violated for subnormals, but ldexp(frexp(x)) == x\n *   still holds (the round-trip is an identity). Code that depends on a\n *   normalized mantissa (e.g., counting significant bits) should not use\n *   subnormal inputs.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt frexp(Flt x, IntType_t<Flt>* eptr) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return frexp<SimdType_t<Flt>>(SimdType_t<Flt>(x), eptr).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n    IntT ix = bit_cast<IntType_t<Flt>>(x);\n    *eptr = 0;\n    return FloatTraits<Flt>::conditional(\n        nonnormalOrZero<Flt>(ix), x, detail::frexpImpl<Flt>(ix, eptr));\n  }\n}\n\n/**\n * @brief Multiply a float by a power of 2 (bit-accurate).\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored; result is always bit-accurate.\n * @param x Input value.\n * @param e Exponent to apply (x * 2^e).\n * @return @p x * 2^e. Returns @p x unchanged for inf/NaN.\n *   Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt ldexp(Flt x, IntType_t<Flt> e) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return ldexp<SimdType_t<Flt>>(SimdType_t<Flt>(x), e).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n    IntT hx = bit_cast<IntT>(x);\n\n    return FloatTraits<Flt>::conditional(nonnormal<Flt>(hx), x, detail::ldexpImpl<Flt>(hx, e));\n  }\n}\n\n/**\n * @brief Arc cosine approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP. kMaxAccuracy: 2 ULP (degree-8 polynomial).\n * @param x Input value in [-1, 1].\n * @return Arc cosine of @p x in radians. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt acos(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return acos<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    BoolType_t<Flt> xneg = x < 0.0f;\n    // abs\n    UintType_t<Flt> xi = bit_cast<UintType_t<Flt>>(x);\n    xi &= 0x7fffffff;\n    x = bit_cast<Flt>(xi);\n\n    // acos(x) = sqrt(1-x) * P(x), where P approximates acos(x)/sqrt(1-x) on [0, 1).\n    // Horner (not Estrin): Estrin regresses acos ULP from 3 to 4.\n    Flt y;\n    if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n      // Sollya fpminimax(acos(x)/sqrt(1-x), 8, [|SG...|], [0, 1-1b-23]):\n      //   sup-norm error < 2^-25.\n      y = dispenso::fast_math::hornerEval(\n          x,\n          0x1.d129f2p-11f,\n          -0x1.3ca11ap-8f,\n          0x1.9a3376p-7f,\n          -0x1.6a1a08p-6f,\n          0x1.10b838p-5f,\n          -0x1.a0365ep-5f,\n          0x1.6cce04p-4f,\n          -0x1.b7820cp-3f,\n          0x1.921fb6p0f);\n    } else {\n      // Sollya fpminimax(acos(x)/sqrt(1-x), 7, [|SG...|], [0, 1-1b-23]):\n      //   sup-norm error < 2^-24.\n      y = dispenso::fast_math::hornerEval(\n          x,\n          -0x1.39a988p-10f,\n          0x1.a50fdp-8f,\n          -0x1.120206p-6f,\n          0x1.f5a1e2p-6f,\n          -0x1.9a1efp-5f,\n          0x1.6c5d48p-4f,\n          -0x1.b77e7ep-3f,\n          0x1.921fb4p0f);\n    }\n\n    auto sqrt1mx = FloatTraits<Flt>::sqrt(1.0f - x);\n    return FloatTraits<Flt>::conditional(\n        xneg, FloatTraits<Flt>::fma(y, -sqrt1mx, Flt(kPi)), y * sqrt1mx);\n  }\n}\n\n/**\n * @brief Arc sine approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 2 ULP. kMaxAccuracy: 1 ULP (higher-degree polynomials).\n * @param x Input value in [-1, 1].\n * @return Arc sine of @p x in radians. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt asin(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return asin<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n\n    IntT xi = bit_cast<IntT>(x);\n    IntT sgnbit = xi & 0x80000000;\n    xi &= 0x7fffffff;\n    x = bit_cast<Flt>(xi);\n\n    Flt ret;\n    if constexpr (std::is_same_v<Flt, float>) {\n      if (xi > 0x3f000000) { // x > 0.5\n        ret = detail::asin_pt5_1<Flt, AccuracyTraits>(x);\n\n      } else {\n        ret = detail::asin_0_pt5<Flt, AccuracyTraits>(x);\n      }\n    } else {\n      // Use compensating sum for better rounding.\n      auto y = detail::asin_pt5_1<Flt, AccuracyTraits>(x);\n      auto z = detail::asin_0_pt5<Flt, AccuracyTraits>(x);\n      ret = FloatTraits<Flt>::conditional(xi > 0x3f000000, y, z); // choose between correct estimate\n    }\n    return bit_cast<Flt>(sgnbit | bit_cast<IntT>(ret));\n  }\n}\n\n/**\n * @brief Sine approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits kMaxAccuracy uses higher-precision range reduction.\n *   Default: 2 ULP in [-2^20 pi, 2^20 pi]; accuracy degrades for larger |x|.\n * @param x Input value in radians (all float domain).\n * @return Sine of @p x. Compatible with all SIMD backends.\n *\n * Scalar: pi/4 reduction with quadrant branching (lowest latency).\n * SIMD:   pi reduction, single sin polynomial, sign flip (no blending, ~30-40% faster).\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt sin(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return sin<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar: pi/4 reduction + branch selects sin or cos polynomial per quadrant.\n    constexpr float kPi_2hi = 1.57079625f;\n    constexpr float kPi_2med = 7.54978942e-08f;\n    constexpr float kPi_2lo = 5.39032794e-15f;\n    constexpr float k2_pi = 0.636619747f;\n    Flt j = detail::rangeReduce2(x, k2_pi, kPi_2hi, kPi_2med, kPi_2lo);\n    return detail::sincos_pi_impl(x, j, 0);\n  } else {\n    // SIMD: pi reduction — single sin_pi_2 polynomial, sign flip, no blending.\n    constexpr float kPi_hi = 3.1415925f;\n    constexpr float kPi_med = 1.50995788e-07f;\n    constexpr float kPi_lo = 1.07806559e-14f;\n    constexpr float k1_pi = 0.318309886f;\n    Flt j = detail::rangeReduce2(x, k1_pi, kPi_hi, kPi_med, kPi_lo);\n    return detail::sin_pi_reduction(x, j);\n  }\n}\n\n/**\n * @brief Cosine approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits kMaxAccuracy uses 4-part Cody-Waite range reduction.\n *   Default: 2 ULP in [-2^15 pi, 2^15 pi].\n *   MaxAccuracy: 2 ULP in [-2^20 pi, 2^20 pi].\n * @param x Input value in radians (all float domain).\n * @return Cosine of @p x. Compatible with all SIMD backends.\n *\n * Scalar: pi/4 reduction with quadrant branching (lowest latency).\n * SIMD:   offset-pi reduction (q = 2*trunc(|x|/pi)+1), single sin polynomial,\n *         sign flip (no blending, ~30% faster).\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt cos(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return cos<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar: pi/4 reduction + branch selects sin or cos polynomial per quadrant.\n    Flt j;\n    if constexpr (AccuracyTraits::kMaxAccuracy) {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2medh = 7.54978942e-08f;\n      constexpr float kPi_2medl = 5.39030253e-15f;\n      constexpr float kPi_2lo = 3.28200367e-22f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce3(x, k2_pi, kPi_2hi, kPi_2medh, kPi_2medl, kPi_2lo);\n    } else {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2med = 7.54978942e-08f;\n      constexpr float kPi_2lo = 5.39032794e-15f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce2(x, k2_pi, kPi_2hi, kPi_2med, kPi_2lo);\n    }\n    return detail::sincos_pi_impl(x, j, 1);\n  } else {\n    // SIMD: offset-pi reduction maps cos zeros to x_r = 0, then evaluates sin_pi_2.\n    auto fma = FloatTraits<Flt>::fma;\n    Flt y = fabs(x);\n    constexpr float k1_pi = 0.318309886f;\n    auto qi = convert_to_int_trunc(y * k1_pi);\n    qi = qi + qi + 1;\n    Flt qf = Flt(qi);\n    if constexpr (AccuracyTraits::kMaxAccuracy) {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2medh = 7.54978942e-08f;\n      constexpr float kPi_2medl = 5.39030253e-15f;\n      constexpr float kPi_2lo = 3.28200367e-22f;\n      y = fma(qf, Flt(-kPi_2hi), y);\n      y = fma(qf, Flt(-kPi_2medh), y);\n      y = fma(qf, Flt(-kPi_2medl), y);\n      y = fma(qf, Flt(-kPi_2lo), y);\n    } else {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2med = 7.54978942e-08f;\n      constexpr float kPi_2lo = 5.39032794e-15f;\n      y = fma(qf, Flt(-kPi_2hi), y);\n      y = fma(qf, Flt(-kPi_2med), y);\n      y = fma(qf, Flt(-kPi_2lo), y);\n    }\n    return detail::cos_offset_pi_reduction(y, qi);\n  }\n}\n\n/**\n * @brief Simultaneous sine and cosine, sharing range reduction.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Same behavior as sin/cos: kMaxAccuracy controls\n *   range reduction precision. Default: 2 ULP each.\n * @param x Input value in radians (all float domain).\n * @param[out] out_sin Pointer to receive sin(x).\n * @param[out] out_cos Pointer to receive cos(x).\n * @note Can be faster than separate sin() + cos() calls due to shared range\n *   reduction and polynomial evaluation (SIMD). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE void sincos(Flt x, Flt* out_sin, Flt* out_cos) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    SimdType_t<Flt> s, c;\n    sincos<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x), &s, &c);\n    *out_sin = s.v;\n    *out_cos = c.v;\n  } else {\n    Flt j;\n    if constexpr (AccuracyTraits::kMaxAccuracy) {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2medh = 7.54978942e-08f;\n      constexpr float kPi_2medl = 5.39030253e-15f;\n      constexpr float kPi_2lo = 3.28200367e-22f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce3(x, k2_pi, kPi_2hi, kPi_2medh, kPi_2medl, kPi_2lo);\n    } else {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2med = 7.54978942e-08f;\n      constexpr float kPi_2lo = 5.39032794e-15f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce2(x, k2_pi, kPi_2hi, kPi_2med, kPi_2lo);\n    }\n    detail::sincos_pi_impl_both(x, j, out_sin, out_cos);\n  }\n}\n\n/**\n * @brief Compute sin(pi * x) with exact range reduction.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored (range reduction is always exact).\n * @param x Input value (all float domain). Exact at integers (returns 0) and\n *   half-integers (returns ±1). ~2 ULP for general inputs.\n * @return sin(pi * x). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt sinpi(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return sinpi<SimdType_t<Flt>>(SimdType_t<Flt>(x)).v;\n  } else {\n    // Exact range reduction: j = round(2*x), r = x - j/2, t = r * pi.\n    constexpr float kMagic = FloatTraits<Flt>::kMagic; // 1.5 * 2^23\n    Flt j = (2.0f * x + kMagic) - kMagic; // round(2*x)\n    Flt r = x - j * 0.5f; // exact for |x| < 2^22\n    Flt t = r * kPi; // only error source\n    return detail::sincos_pi_impl(t, j, 0);\n  }\n}\n\n/**\n * @brief Compute cos(pi * x) with exact range reduction.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored (range reduction is always exact).\n * @param x Input value (all float domain). Exact at integers (returns ±1) and\n *   half-integers (returns 0). ~2 ULP for general inputs.\n * @return cos(pi * x). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt cospi(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return cospi<SimdType_t<Flt>>(SimdType_t<Flt>(x)).v;\n  } else {\n    constexpr float kMagic = FloatTraits<Flt>::kMagic;\n    Flt j = (2.0f * x + kMagic) - kMagic;\n    Flt r = x - j * 0.5f;\n    Flt t = r * kPi;\n    return detail::sincos_pi_impl(t, j, 1);\n  }\n}\n\n/**\n * @brief Simultaneous sin(pi*x) and cos(pi*x) with exact range reduction.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Accepted but ignored.\n * @param x Input value (all float domain).\n * @param[out] out_sin Pointer to receive sin(pi * x).\n * @param[out] out_cos Pointer to receive cos(pi * x).\n * @note Faster than separate sinpi() + cospi() calls. ~2 ULP each.\n *   Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE void sincospi(Flt x, Flt* out_sin, Flt* out_cos) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    SimdType_t<Flt> s, c;\n    sincospi<SimdType_t<Flt>>(SimdType_t<Flt>(x), &s, &c);\n    *out_sin = s.v;\n    *out_cos = c.v;\n  } else {\n    constexpr float kMagic = FloatTraits<Flt>::kMagic;\n    Flt j = (2.0f * x + kMagic) - kMagic;\n    Flt r = x - j * 0.5f;\n    Flt t = r * kPi;\n    detail::sincos_pi_impl_both(t, j, out_sin, out_cos);\n  }\n}\n\n/**\n * @brief Tangent approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP in [-256K pi, 256K pi].\n *   kMaxAccuracy uses 4-part Cody-Waite reduction for wider accurate range.\n * @param x Input value in radians; undefined at odd multiples of pi/2.\n * @return Tangent of @p x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt tan(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return tan<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    Flt j;\n    if constexpr (AccuracyTraits::kMaxAccuracy) {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2medh = 7.54978942e-08f;\n      constexpr float kPi_2medl = 5.39030253e-15f;\n      constexpr float kPi_2lo = 3.28200367e-22f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce3(x, k2_pi, kPi_2hi, kPi_2medh, kPi_2medl, kPi_2lo);\n    } else {\n      constexpr float kPi_2hi = 1.57079625f;\n      constexpr float kPi_2med = 7.54978942e-08f;\n      constexpr float kPi_2lo = 5.39032794e-15f;\n      constexpr float k2_pi = 0.636619747f;\n      j = detail::rangeReduce2(x, k2_pi, kPi_2hi, kPi_2med, kPi_2lo);\n    }\n    return detail::tan_pi_2_impl(x, j);\n  }\n}\n\n/**\n * @brief Arc tangent approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP. kMaxAccuracy: 2 ULP (degree-11 polynomial).\n * @param x Input value (all float domain).\n * @return Arc tangent of @p x in radians. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt atan(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return atan<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n\n    IntT xi = bit_cast<IntT>(x);\n    IntT sgnbit = xi & 0x80000000;\n    xi &= 0x7fffffff;\n    x = bit_cast<Flt>(xi);\n\n    auto flip = x > 1.0f;\n    // TODO(bbudge): Verify, Some compilers (MSVC) don't optimize this as well, check for scalar\n    // case.\n    if constexpr (std::is_same_v<Flt, float>) {\n      if (flip) {\n        x = 1.0f / x;\n      }\n    } else {\n      x = FloatTraits<Flt>::conditional(flip, 1.0f / x, x);\n    }\n\n    auto y = detail::atan_poly<Flt, AccuracyTraits>(x);\n\n    y = FloatTraits<Flt>::conditional(flip, kPi_2 - y, y);\n\n    y = bit_cast<Flt>(bit_cast<IntT>(y) | sgnbit);\n\n    return y;\n  }\n}\n\n/**\n * @brief Base-2 exponential approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 1 ULP. kMaxAccuracy has no additional effect.\n *   kBoundsValues: returns NaN for NaN, clamps input to avoid overflow.\n * @param x Input value; [-127, 128] for normal output.\n * @return 2^x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt exp2(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return exp2<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n\n    Flt xf;\n    IntT xi;\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      if constexpr (std::is_same_v<float, Flt>) {\n        if (!(x == x)) {\n          return x;\n        }\n        x = clamp_allow_nan(x, -127.0f, 128.0f);\n        xf = floor_small(x);\n        xi = convert_to_int(xf);\n      } else {\n        // bool_as_mask converts any comparison result (lane-wide or __mmask16)\n        // to IntType uniformly across all SIMD backends.\n        IntType_t<Flt> nonanmask = bool_as_mask<IntType_t<Flt>>(x == x);\n        x = clamp_allow_nan(x, Flt(-127.0f), Flt(128.0f));\n        xf = floor_small(x);\n        xi = nonanmask & convert_to_int(xf);\n      }\n    } else {\n      xf = floor_small(x);\n      xi = convert_to_int(xf);\n    }\n\n    x -= xf;\n    xi += 127;\n    xi <<= 23;\n\n    Flt powxi = bit_cast<Flt>(xi);\n\n    Flt y = dispenso::fast_math::hornerEval(\n        x,\n        0x1.c41242p-13f,\n        0x1.4748aep-10f,\n        0x1.3cfb6p-7f,\n        0x1.c68b2ep-5f,\n        0x1.ebfd38p-3f,\n        0x1.62e42cp-1f,\n        0x1p0f);\n\n    return powxi * y;\n  }\n}\n\n/**\n * @brief Natural exponential approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP. MaxAccuracy: 1 ULP (Sollya-optimized\n *   polynomial + Norbert Juffa's rounding technique).\n *   kBoundsValues: returns 0 for large negative, inf for large positive, NaN for NaN.\n * @param x Input value; [-89, 89] for normal output.\n * @return e^x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt exp(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return exp<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n    using UintT = UintType_t<Flt>;\n    constexpr float k1_ln2 = k1_Ln2;\n    constexpr float kLn2hi = 6.93145752e-1f;\n    constexpr float kLn2lo = 1.42860677e-6f;\n\n    if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n      // Rounding algorithm courtesy Norbert Juffa, https://stackoverflow.com/a/40519989/830441\n      // exp(x) = 2**i * exp(f); i = rintf (x / log(2))\n      Flt f = x;\n      Flt j = detail::rangeReduce(f, k1_ln2, kLn2hi, kLn2lo);\n      IntT i = convert_to_int(j);\n      // approximate r = exp(f) on interval [-log(2)/2, +log(2)/2]\n      Flt y = dispenso::fast_math::hornerEval(\n          f,\n          0x1.6850e4p-10f,\n          0x1.123bccp-7f,\n          0x1.555b98p-5f,\n          0x1.55548ep-3f,\n          0x1.fffff8p-2f,\n          1.f,\n          1.f);\n      // exp(x) = 2**i * y (with rounding)\n      auto ipos = i > IntT(0);\n      UintT ia = FloatTraits<Flt>::conditional(ipos, UintT(0u), UintT(0x83000000u));\n      Flt s = bit_cast<Flt>(UintT(0x7f000000u) + ia);\n      Flt t = bit_cast<Flt>((UintT(i) << 23) - ia);\n      y = y * s;\n      y = y * t;\n      if constexpr (AccuracyTraits::kBoundsValues) {\n        if constexpr (std::is_same_v<float, Flt>) {\n          auto zero = (x < -89.0f);\n          auto overflow = (x > 89.0f);\n          if ((zero || overflow)) {\n            Flt orbits = bit_cast<Flt>(bool_apply_or_zero(overflow, 0x7f800000));\n            y = FloatTraits<Flt>::conditional(zero | overflow, orbits, y);\n          }\n        } else {\n          auto zero = (x < -89.0f);\n          auto overflow = (x > 89.0f);\n          IntT orbits = bool_apply_or_zero<IntT>(overflow, IntT(0x7f800000));\n          auto mask = bool_as_mask<IntT>(zero) | bool_as_mask<IntT>(overflow);\n          y = FloatTraits<Flt>::conditional(mask, bit_cast<Flt>(orbits), y);\n        }\n      }\n      return y;\n    } else {\n      Flt j = detail::rangeReduceFloor(x, k1_ln2, kLn2hi, kLn2lo);\n      IntT xi = convert_to_int(j);\n\n      xi += 127;\n      xi <<= 23;\n\n      Flt powxi = bit_cast<Flt>(xi);\n\n      // approximate r = exp(f) on interval [0, ln2]\n      Flt y = dispenso::fast_math::hornerEval(\n          x,\n          0x1.8014dp-7f,\n          0x1.3f3846p-5f,\n          0x1.57481ep-3f,\n          0x1.ffd96ep-2f,\n          0x1.000086p0f,\n          0x1.fffffep-1f);\n\n      return powxi * y;\n    }\n  }\n}\n\n/**\n * @brief Base-10 exponential approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 2 ULP. kBoundsValues: handles NaN.\n * @param x Input value; [-38, 38] for normal output.\n * @return 10^x. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt exp10(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return exp10<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n    constexpr double kLog10of2d = 0.3010299956639812;\n    constexpr float k1_log10of2 = static_cast<float>(1.0 / kLog10of2d);\n    constexpr float kLog10of2 = static_cast<float>(kLog10of2d);\n    constexpr float kLog10of2lo = static_cast<float>(kLog10of2d - kLog10of2);\n\n    Flt j;\n    IntT xi;\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      IntType_t<Flt> nonanmask = bool_as_mask<IntType_t<Flt>>(x == x);\n\n      x = clamp_allow_nan(x, Flt(-38.23080944932561f), Flt(38.53183944498959f));\n      j = detail::rangeReduceFloor(x, k1_log10of2, kLog10of2, kLog10of2lo);\n      xi = nonanmask & convert_to_int(j);\n    } else {\n      j = detail::rangeReduceFloor(x, k1_log10of2, kLog10of2, kLog10of2lo);\n      xi = convert_to_int(j);\n    }\n\n    xi += 127;\n    xi <<= 23;\n\n    Flt powxi = bit_cast<Flt>(xi);\n    Flt y = dispenso::fast_math::hornerEval(\n        x,\n        0x1.293a54p-2f,\n        0x1.024feap-1f,\n        0x1.2d9da2p0f,\n        0x1.0459f6p1f,\n        0x1.53534cp1f,\n        0x1.26bb18p1f,\n        0x1p0f);\n\n    return powxi * y;\n  }\n}\n\n/**\n * @brief Base-2 logarithm approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 1 ULP. kMaxAccuracy handles denormals correctly.\n *   kBoundsValues: returns -inf for 0, NaN for negative, +inf for +inf.\n * @param x Input value in (0, +inf).\n * @return log2(x). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt log2(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return log2<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    auto [xi, i, m] = detail::logarithmSep<Flt, AccuracyTraits>(x);\n\n    m = m - 1.0f;\n\n    // Compute log2(1+m) for m in [sqrt(0.5)-1, sqrt(2.0)-1]\n    // Degree-9 polynomial with c0=0 absorbed: the Horner chain evaluates c9..c1,\n    // then fma(y, m, m) applies the final y*m + m (since c0=0, c1 is folded into +m).\n    Flt y = dispenso::fast_math::hornerEval(\n        m,\n        -1.09985352e-1f,\n        1.86182275e-1f,\n        -1.91066533e-1f,\n        2.04593703e-1f,\n        -2.39627063e-1f,\n        2.88573444e-1f,\n        -3.60695332e-1f,\n        4.80897635e-1f,\n        -7.21347392e-1f,\n        4.42695051e-1f);\n    y = FloatTraits<Flt>::fma(y, m, m); // c0=0 absorbed: y*m + m\n\n    y = y + i;\n\n    /* Check for and handle special cases */\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      y = detail::logarithmBounds(x, y, xi);\n    }\n\n    return y;\n  }\n}\n\n/**\n * @brief Natural logarithm approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 2 ULP. kMaxAccuracy handles denormals correctly.\n *   kBoundsValues: returns -inf for 0, NaN for negative, +inf for +inf.\n * @param x Input value in (0, +inf).\n * @return ln(x). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt log(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return log<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    auto [xi, i, m] = detail::logarithmSep<Flt, AccuracyTraits>(x);\n\n    m = m - 1.0f;\n\n    // Compute log(1+m) for m in [sqrt(0.5)-1, sqrt(2.0)-1]\n    // Degree-9 polynomial with c0=0, c1=1 absorbed: y = P(m)*m² + m.\n    // P(m) evaluates c9..c2 (8 coefficients), then fma(P, m², m) applies c1=1 and c0=0.\n    Flt y = dispenso::fast_math::hornerEval(\n        m,\n        0.0924733654f,\n        -0.14482744f,\n        0.148145974f,\n        -0.165455937f,\n        0.199700251f,\n        -0.250024557f,\n        0.333337069f,\n        -0.499999911f);\n    y = FloatTraits<Flt>::fma(y, m * m, m); // c0=0, c1=1 absorbed\n\n    y = FloatTraits<Flt>::fma(i, kLn2, y);\n\n    /* Check for and handle special cases */\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      y = detail::logarithmBounds(x, y, xi);\n    }\n\n    return y;\n  }\n}\n\n/**\n * @brief Base-10 logarithm approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP. kMaxAccuracy handles denormals correctly.\n *   kBoundsValues: returns -inf for 0, NaN for negative, +inf for +inf.\n * @param x Input value in (0, +inf).\n * @return log10(x). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt log10(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return log10<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    auto [xi, i, m] = detail::logarithmSep<Flt, AccuracyTraits>(x);\n\n    m = m - 1.0f;\n\n    // Compute log10(1+m) for m in [sqrt(0.5)-1, sqrt(2.0)-1]\n    auto fma = FloatTraits<Flt>::fma;\n    // Degree-9 polynomial with c0=0 absorbed: y = P(m) * m, where\n    // P(m) = c9*m^8 + ... + c1 (9 coefficients).\n    Flt y = dispenso::fast_math::hornerEval(\n                m,\n                0.0326662175f,\n                -0.0601400957f,\n                0.0659840927f,\n                -0.0723559037f,\n                0.086600922f,\n                -0.108560629f,\n                0.144770443f,\n                -0.217147425f,\n                0.434294462f) *\n        m;\n\n    constexpr float kLog10of2 = 0.30102999566398f;\n    y = fma(i, kLog10of2, y);\n\n    /* Check for and handle special cases */\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      y = detail::logarithmBounds(x, y, xi);\n    }\n\n    return y;\n  }\n}\n\n/**\n * @brief Two-argument arc tangent approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: 3 ULP. kMaxAccuracy: 2 ULP (degree-11 polynomial).\n *   kBoundsValues: handles the case where both arguments are inf.\n * @param y Y coordinate (all float domain).\n * @param x X coordinate (all float domain).\n * @return atan2(y, x) in radians. Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt atan2(Flt y, Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return atan2<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(y), SimdType_t<Flt>(x)).v;\n  } else {\n    using UintT = UintType_t<Flt>;\n    UintT yi = bit_cast<UintT>(y);\n    UintT xi = bit_cast<UintT>(x);\n\n    auto someNonzero = ((yi | xi) & 0x7fffffff) != 0;\n\n    UintT xsgn = xi & 0x80000000;\n    UintT ysgn = yi & 0x80000000;\n    UintT allsgn = xsgn ^ ysgn;\n\n    yi &= 0x7fffffff;\n    xi &= 0x7fffffff;\n\n    auto flip = yi > xi;\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      using IntT = IntType_t<Flt>;\n      auto yinf = yi == UintT(0x7f800000u);\n      auto bothinf = (yinf & (xi == UintT(0x7f800000u)));\n      auto bothinfi = bool_as_mask<IntT>(bothinf);\n      yi = FloatTraits<Flt>::conditional(bothinfi, UintT(0x7f7fffffu), yi);\n      xi = FloatTraits<Flt>::conditional(bothinfi, UintT(0x7f7fffffu), xi);\n      // keepsgn = NOT(yinf AND NOT bothinf) = bothinf OR NOT yinf.\n      auto keepsgn = !((!bothinf) & yinf);\n      xsgn &= bool_as_mask<UintT>(keepsgn);\n    }\n\n    Flt den = bit_cast<Flt>(FloatTraits<Flt>::conditional(flip, yi, xi));\n    Flt num = bit_cast<Flt>(FloatTraits<Flt>::conditional(flip, xi, yi));\n\n    Flt y_x = bool_apply_or_zero(someNonzero, num / den);\n\n    auto z = detail::atan_poly<Flt, AccuracyTraits>(y_x);\n\n    z = FloatTraits<Flt>::conditional(flip, kPi_2 - z, z);\n\n    z = bit_cast<Flt>(bit_cast<UintT>(z) | allsgn);\n\n    // Branchless offset: π where x<0, 0 where x≥0, with y's sign applied.\n    UintT x_neg_mask = UintT(0) - (xsgn >> 31);\n    Flt pi_or_zero = bit_cast<Flt>(x_neg_mask & bit_cast<UintT>(Flt(kPi)));\n    Flt offset = bit_cast<Flt>(bit_cast<UintT>(pi_or_zero) | ysgn);\n    return z + offset;\n  }\n}\n\n/**\n * @brief Hypotenuse: sqrt(x*x + y*y) with overflow protection.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~1 ULP for all normal floats.\n *   kBoundsValues: handles inf/NaN per IEEE 754 (hypot(inf,NaN) = +inf).\n *   kMaxAccuracy: accepted but has no additional effect.\n * @param x First input (all float domain).\n * @param y Second input (all float domain).\n * @return sqrt(x*x + y*y). Compatible with all SIMD backends.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt hypot(Flt x, Flt y) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return hypot<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x), SimdType_t<Flt>(y)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      uint32_t ax = bit_cast<uint32_t>(x) & 0x7fffffffu;\n      uint32_t ay = bit_cast<uint32_t>(y) & 0x7fffffffu;\n      if (DISPENSO_EXPECT(ax == 0x7f800000u || ay == 0x7f800000u, 0)) {\n        return std::numeric_limits<float>::infinity();\n      }\n      if (DISPENSO_EXPECT(ax > 0x7f800000u || ay > 0x7f800000u, 0)) {\n        return std::numeric_limits<float>::quiet_NaN();\n      }\n    }\n    // Scalar: cast to double for correctly-rounded result.\n    double xd = static_cast<double>(x);\n    double yd = static_cast<double>(y);\n    return static_cast<float>(std::sqrt(std::fma(xd, xd, yd * yd)));\n  } else {\n    // SIMD: dynamically scale inputs based on their exponent to keep\n    // intermediates in normal float range.  Extracts the exponent of\n    // max(|x|,|y|), builds scale = 2^(127-E) so the scaled max is in [1,2).\n    // Clamp ensures the scale itself stays in normal range.\n    using IntT = IntType_t<Flt>;\n    using UintT = UintType_t<Flt>;\n    Flt abs_mask = bit_cast<Flt>(UintT(0x7fffffffu));\n    Flt max_abs = FloatTraits<Flt>::max(x & abs_mask, y & abs_mask);\n    // Clamp to [FLT_MIN, 2^126] so scale and unscale stay normal.\n    Flt clamped =\n        FloatTraits<Flt>::max(FloatTraits<Flt>::min(max_abs, Flt(0x1p126f)), Flt(0x1p-126f));\n    IntT clamped_exp = bit_cast<IntT>(clamped) & IntT(0x7f800000);\n    // scale = 2^(127-E), unscale = 2^(E-127).\n    Flt scale = bit_cast<Flt>(IntT(0x7f000000) - clamped_exp);\n    Flt xs = x * scale;\n    Flt ys = y * scale;\n    auto fma = FloatTraits<Flt>::fma;\n    Flt h = FloatTraits<Flt>::sqrt(fma(xs, xs, ys * ys));\n    // Newton refinement: h' = h + (xs²+ys²-h²) * rcp(2h)\n    Flt r = fma(xs, xs, fma(ys, ys, -(h * h)));\n    Flt rcp_2h = FloatTraits<Flt>::rcp(h + h + Flt(std::numeric_limits<float>::min()));\n    h = fma(r, rcp_2h, h);\n    Flt unscale = bit_cast<Flt>(clamped_exp);\n    h = h * unscale;\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      // IEEE 754: hypot(±inf, y) = +inf even when y is NaN.\n      // Inf inputs produce NaN through Newton refinement, so override here.\n      UintT ax = bit_cast<UintT>(x) & UintT(0x7fffffffu);\n      UintT ay = bit_cast<UintT>(y) & UintT(0x7fffffffu);\n      auto either_inf = (ax == UintT(0x7f800000u)) | (ay == UintT(0x7f800000u));\n      auto inf_mask = bool_as_mask<IntT>(either_inf);\n      h = FloatTraits<Flt>::conditional(inf_mask, bit_cast<Flt>(UintT(0x7f800000u)), h);\n    }\n    return h;\n  }\n}\n\n/**\n * @brief Power function: x^y.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~1 ULP for scalar float (double-precision core),\n *   error scales as |y*log2(x)|*ln2 ULP for SIMD (~1-2 for moderate y).\n *   kMaxAccuracy: uses extended-precision log2 for ~1-2 ULP even for large y (SIMD only;\n *   scalar float always uses the double-precision core which subsumes this).\n *   kBoundsValues: full IEEE 754 special-case handling (NaN, Inf, zero, negative bases).\n * @param x Base (all float domain, including negative).\n * @param y Exponent (SIMD vector).\n * @return x^y. Negative x: returns -|x|^y for odd integer y, NaN for non-integer y.\n *   Compatible with all SIMD backends.\n *\n * Scalar float uses a table-based double-precision core (~2.5ns).\n * SIMD uses float-precision exp2/log2 with FMA error-free transform.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt pow(Flt x, NonDeduced<Flt> y) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return pow<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x), SimdType_t<Flt>(y)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar float: double-precision pow core (table-based log2 + exp2).\n    // Uses integer checkint() for parity (~5 insns vs ~40 for float_is_int/odd).\n    // Branchless sign XOR. Table entry i=9 is {1.0, 0.0} so pow(1,y) = 1 exactly.\n    uint32_t ix = bit_cast<uint32_t>(x);\n    uint32_t iy = bit_cast<uint32_t>(y);\n    // sign_bias is 0x80000000u for odd-integer y with negative x, else 0.\n    // Always XORed into the result (no-op when 0).\n    uint32_t sign_bias = 0;\n    // neg_nan: set if negative x with non-integer y (domain error → NaN).\n    // Only used by the non-bounds path (deferred after core computation).\n    uint32_t neg_nan = 0;\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      // Combined fast-path test: detects any x or y that needs special handling.\n      // First term: ix - 0x00800000 >= 0x7F000000 is true when ix < 0x00800000\n      // (zero, subnormal) or ix >= 0x7F800000 (inf, NaN) — but also when ix\n      // has the sign bit set (negative), because unsigned subtraction wraps\n      // to a huge value. This means negative x enters the special block too,\n      // avoiding a separate negative-x check.\n      // Second term: 2u*iy - 1u >= 0xFEFFFFFF tests y = ±0, ±inf, or NaN\n      // (see bit trick comments in pow_scalar_y_special).\n      if (DISPENSO_EXPECT(\n              ix - 0x00800000u >= 0x7f800000u - 0x00800000u ||\n                  2u * iy - 1u >= 2u * 0x7f800000u - 1u,\n              0)) {\n        float special;\n        if (2u * iy - 1u >= 2u * 0x7f800000u - 1u) {\n          detail::pow_scalar_y_special(x, y, ix, iy, &special);\n          return special;\n        }\n        if (detail::pow_scalar_x_special(ix, iy, sign_bias, &special))\n          return special;\n        // Fall through to core computation with adjusted ix.\n      }\n    } else {\n      // Non-bounds path: one branch for the common case (positive x),\n      // branchless checkint in the else (rare negative-x path avoids further mispredicts).\n      if (DISPENSO_EXPECT(!(ix & 0x80000000u), 1)) {\n        // Positive x: nothing to do.\n      } else {\n        ix &= 0x7fffffffu;\n        int32_t yint = detail::checkint_branchless(iy);\n        sign_bias = static_cast<uint32_t>(yint == 2) * 0x80000000u;\n        neg_nan = static_cast<uint32_t>(yint == 0);\n      }\n    }\n\n    float r;\n    if constexpr (AccuracyTraits::kMaxAccuracy) {\n      // Tableless core: logarithmSep handles subnormals internally (pre-scales\n      // by 2^23), so pass the original |x| — not the bounds-adjusted ix.\n      r = detail::pow_double_poly_core(std::fabs(x), y);\n    } else {\n      // Table core: uses ix directly. The bounds path above already normalized\n      // subnormals (scale by 2^23, subtract 23 from exponent) so ix is valid.\n      r = detail::pow_double_core(bit_cast<float>(ix), y);\n    }\n\n    // Branchless sign flip (no-op when sign_bias == 0).\n    r = bit_cast<float>(bit_cast<uint32_t>(r) ^ sign_bias);\n    // Non-bounds: apply deferred NaN for neg^non-int, and pow(x,0)=1.\n    if constexpr (!AccuracyTraits::kBoundsValues) {\n      if (neg_nan)\n        r = std::numeric_limits<float>::quiet_NaN();\n      if (y == 0.0f)\n        r = 1.0f;\n    }\n\n    return r;\n  } else {\n    // SIMD path: double-precision core for all accuracy levels (~1 ULP).\n    using UintT = UintType_t<Flt>;\n\n    Flt ax = fabs(x);\n    Flt r;\n\n    // Width-dependent dispatch: table gathers are cheap at 4 lanes but\n    // scale poorly; polynomial cost amortizes over more lanes.\n    if constexpr (sizeof(Flt) <= 16) {\n      r = detail::pow_double_hybrid_core(ax, y);\n    } else {\n      r = detail::pow_double_poly_core(ax, y);\n    }\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      detail::pow_simd_special_fixup(ax, y, r);\n    }\n\n    // Sign handling for negative x (SIMD, branchless per-lane):\n    // The double core computes pow(|x|, y). For negative x we need:\n    //   - odd integer y:     negate result (e.g. pow(-2, 3) = -8)\n    //   - even integer y:    keep positive (e.g. pow(-2, 2) = 4)\n    //   - non-integer y:     result is NaN (domain error)\n    // float_is_int/float_is_odd test this via mantissa bit inspection\n    // (branchless SIMD comparisons, no scalar checkint needed).\n    UintT xsign = bit_cast<UintT>(x) & UintT(0x80000000u);\n    auto negx = x < 0.0f;\n    auto y_int = float_is_int(y);\n    auto y_odd = float_is_odd(y);\n    // sign_mask is 0x80000000 in lanes where x < 0 AND y is odd, else 0.\n    // XORing into r negates exactly those lanes.\n    UintT sign_mask = xsign & bool_as_mask<UintT>(y_odd);\n    r = bit_cast<Flt>(bit_cast<UintT>(r) ^ sign_mask);\n    // Replace with NaN where x < 0 and y is not an integer.\n    constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();\n    r = FloatTraits<Flt>::conditional(negx & !y_int, Flt(kNaN), r);\n\n    // pow(x, 0) = 1 for all x (IEEE 754).\n    r = FloatTraits<Flt>::conditional(y == 0.0f, Flt(1.0f), r);\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      // pow(1, y) = 1 even for NaN y.\n      r = FloatTraits<Flt>::conditional(x == 1.0f, Flt(1.0f), r);\n      // pow(-1, ±inf) = 1.\n      constexpr float kInf = std::numeric_limits<float>::infinity();\n      auto x_neg1 = (x == -1.0f);\n      auto y_inf = fabs(y) == Flt(kInf);\n      r = FloatTraits<Flt>::conditional(x_neg1 & y_inf, Flt(1.0f), r);\n    }\n\n    return r;\n  }\n}\n\n/**\n * @brief Power function with scalar exponent: x^y.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Same as pow(Flt, Flt).\n * @param x Base (all float domain, including negative).\n * @param y Scalar exponent — enables scalar branching optimizations.\n * @return x^y. Same semantics as pow(Flt, Flt).\n *   Compatible with all SIMD backends.\n *\n * Scalar y enables fast paths: y=0→1, y=1→x, y=-1→1/x, y=0.5→sqrt,\n * y=2→x*x, integer y→binary squaring. General case uses exp2/log2.\n */\ntemplate <\n    typename Flt,\n    typename AccuracyTraits = DefaultAccuracyTraits,\n    typename = std::enable_if_t<!std::is_same_v<Flt, float>>>\nDISPENSO_INLINE Flt pow(Flt x, float y) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return pow<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x), y).v;\n  } else {\n    using UintT = UintType_t<Flt>;\n\n    // Scalar fast paths: y=0→1, y=1→x, y=-1→1/x, y=0.5→sqrt, y=2→x*x,\n    // small integer y → binary squaring.\n    bool y_is_int = false, y_is_odd = false;\n    Flt fast_result;\n    if (detail::pow_scalar_y_fast_path(x, y, y_is_int, y_is_odd, fast_result))\n      return fast_result;\n\n    Flt ax = fabs(x);\n    Flt r;\n    Flt yv(y);\n\n    // Double-precision core for all SIMD accuracy levels (~1 ULP).\n    if constexpr (sizeof(Flt) <= 16) {\n      r = detail::pow_double_hybrid_core(ax, yv);\n    } else {\n      r = detail::pow_double_poly_core(ax, yv);\n    }\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      detail::pow_simd_special_fixup(ax, yv, r);\n    }\n\n    // Sign handling for negative x.\n    if (y_is_odd) {\n      UintT xsign = bit_cast<UintT>(x) & UintT(0x80000000u);\n      r = bit_cast<Flt>(bit_cast<UintT>(r) ^ xsign);\n    }\n    if (!y_is_int) {\n      auto negx = x < 0.0f;\n      constexpr float kNaN = std::numeric_limits<float>::quiet_NaN();\n      r = FloatTraits<Flt>::conditional(negx, Flt(kNaN), r);\n    }\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      r = FloatTraits<Flt>::conditional(x == 1.0f, Flt(1.0f), r);\n      constexpr float kInf = std::numeric_limits<float>::infinity();\n      if (y == kInf || y == -kInf) {\n        auto x_neg1 = (x == -1.0f);\n        r = FloatTraits<Flt>::conditional(x_neg1, Flt(1.0f), r);\n      }\n    }\n\n    return r;\n  }\n}\n\n/**\n * @brief Compute exp(x) - 1 with precision near zero.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~2 ULP (1-step CW + degree-4 poly).\n *   MaxAccuracy: 1 ULP (2-step CW + degree-5 poly).\n *   kBoundsValues: 1 ULP + handles NaN/inf.\n * @param x Input value (all float domain).\n * @return exp(x) - 1. Compatible with all SIMD backends.\n *\n * Uses Cody-Waite range reduction: x = n*ln2 + r, |r| <= ln2/2.\n * Then expm1(x) = 2^n * expm1(r) + (2^n - 1), where expm1(r) is computed\n * via a Sollya fpminimax polynomial. Avoids the catastrophic cancellation of\n * exp(x) - 1 near zero, and provides uniform accuracy across the entire\n * domain (no polynomial/fallback transition).\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt expm1(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return expm1<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    using IntT = IntType_t<Flt>;\n    using UintT = UintType_t<Flt>;\n    auto fma_fn = FloatTraits<Flt>::fma;\n\n    // Cody-Waite range reduction: x = n*ln2 + r, |r| <= ln2/2.\n    // 2-step CW is required for all accuracy levels because the\n    // reconstruction 2^n * expm1(r) amplifies reduction error by 2^n.\n    constexpr float k1_ln2 = k1_Ln2;\n    constexpr float kLn2hi = 6.93145752e-1f;\n    constexpr float kLn2lo = 1.42860677e-6f;\n    Flt r = x;\n    Flt jf = detail::rangeReduce(r, k1_ln2, kLn2hi, kLn2lo);\n    IntT n = convert_to_int(jf);\n\n    Flt em1_r;\n\n    if constexpr (AccuracyTraits::kMaxAccuracy || AccuracyTraits::kBoundsValues) {\n      // Degree-5 Sollya fpminimax((exp(x)-1-x)/x^2, 5, [|SG...|], [-ln2/2, ln2/2]):\n      //   sup-norm error < 2^-29 (~0.03 ULP at r = ln2/2).\n      Flt p = dispenso::fast_math::hornerEval(\n          r,\n          0x1.a26762p-13f,\n          0x1.6d2ep-10f,\n          0x1.110ff2p-7f,\n          0x1.555502p-5f,\n          0x1.555556p-3f,\n          0x1p-1f);\n      em1_r = fma_fn(p, r * r, r);\n    } else {\n      // Degree-4 Sollya fpminimax((exp(x)-1-x)/x^2, 4, [|SG...|], [-ln2/2, ln2/2]):\n      //   sup-norm error < 2^-24 (~1.2 ULP at r = ln2/2).\n      Flt p = dispenso::fast_math::hornerEval(\n          r, 0x1.6ca992p-10f, 0x1.120abep-7f, 0x1.55556cp-5f, 0x1.5554dep-3f, 0x1p-1f);\n      em1_r = fma_fn(p, r * r, r);\n    }\n\n    // Reconstruction: expm1(x) = 2^n * expm1(r) + (2^n - 1).\n    // 2^n is exact for integer n. 2^n - 1 is exact for |n| <= 23.\n    // For |n| > 24, 2^n - 1 = 2^n in float, so expm1 ≈ exp which is correct.\n    // Use fma for precision: fma(2^n, expm1(r), 2^n - 1).\n    Flt two_n = bit_cast<Flt>(UintT(n + 127) << 23);\n    Flt two_n_m1 = two_n - 1.0f;\n    Flt result = fma_fn(two_n, em1_r, two_n_m1);\n\n    if constexpr (std::is_same_v<Flt, float>) {\n      // For n == 0 (|x| < ln2/2 ≈ 0.347): return polynomial directly.\n      if (n == 0)\n        return em1_r;\n      // For x < -25*ln2 ≈ -17.3: expm1(x) rounds to -1 in float.\n      if (x < -17.5f)\n        return -1.0f;\n      // For x > 89: exp(x) overflows, expm1(x) = inf.\n      if (x > 89.0f)\n        return std::numeric_limits<float>::infinity();\n      // NaN propagation: rangeReduce maps NaN to finite r, producing a\n      // garbage result.  x - x is 0 for finite, NaN for NaN.\n      if constexpr (AccuracyTraits::kBoundsValues)\n        return result + (x - x);\n      return result;\n    } else {\n      // SIMD: blend n==0 path (direct polynomial) with reconstruction.\n      auto zero_n = (n == IntT(0));\n      result = FloatTraits<Flt>::conditional(zero_n, em1_r, result);\n      // Clamp: x < -17.5 → -1, x > 89 → inf.\n      result = FloatTraits<Flt>::conditional(x < -17.5f, Flt(-1.0f), result);\n      constexpr float kInf = std::numeric_limits<float>::infinity();\n      result = FloatTraits<Flt>::conditional(x > 89.0f, Flt(kInf), result);\n\n      if constexpr (AccuracyTraits::kBoundsValues) {\n        // NaN propagation: range reduction maps NaN to finite values.\n        auto is_nan = (bit_cast<UintT>(x) & UintT(0x7fffffffu)) > UintT(0x7f800000u);\n        result = FloatTraits<Flt>::conditional(is_nan, x, result);\n      }\n\n      return result;\n    }\n  }\n}\n\n/**\n * @brief Compute log(1 + x) with precision near zero.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~2 ULP. kBoundsValues: handles x = -1 (→ -inf), NaN.\n * @param x Input value in (-1, +inf).\n * @return log(1 + x). Compatible with all SIMD backends.\n *\n * For |x| < 0.25: direct Sollya polynomial avoids the log() call (~1 ULP).\n * For |x| >= 0.25: compensated-addition trick: u = 1 + x, c = x - (u - 1)\n * captures the rounding error. Then log(u) is computed inline via the same\n * range reduction as log() (logarithmSep), and the result is log(u) + c/u.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt log1p(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return log1p<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else {\n    auto fma_fn = FloatTraits<Flt>::fma;\n\n    // Direct polynomial for log1p(x) on [-0.25, 0.25]:\n    //   log1p(x) = x - x²/2 + x³/3 - ... ≈ x + x² * q(x)\n    // Sollya fpminimax((log(1+x)-x)/x^2, 6, [|SG...|], [-0.25, 0.25]):\n    //   sup-norm error < 2^-23; at x=0.25 → ~0.25 ULP polynomial error.\n    Flt q = dispenso::fast_math::hornerEval(\n        x,\n        -0x1.1957b2p-3f,\n        0x1.3f347cp-3f,\n        -0x1.5472d2p-3f,\n        0x1.98bfaap-3f,\n        -0x1.000112p-2f,\n        0x1.555632p-2f,\n        -0x1p-1f);\n    Flt poly_r = fma_fn(q, x * x, x); // log1p(x) ≈ x + x² * q(x)\n\n    if constexpr (std::is_same_v<Flt, float>) {\n      // Scalar: branch on magnitude.\n      if (std::fabs(x) < 0.25f)\n        return poly_r;\n    }\n\n    // Compensated addition: u = float(1 + x), c = rounding error.\n    // log(1 + x) = log(u + c) = log(u) + log(1 + c/u) ≈ log(u) + c/u.\n    Flt u = Flt(1.0f) + x;\n    Flt c = x - (u - 1.0f);\n\n    // Inline log(u): range-reduce u via logarithmSep, evaluate polynomial.\n    auto [xi, i, m] = detail::logarithmSep<Flt, AccuracyTraits>(u);\n    m = m - 1.0f;\n\n    // log(1+m) polynomial for m in [sqrt(0.5)-1, sqrt(2.0)-1].\n    // Same coefficients as log(). Degree-9 with c0=0, c1=1 absorbed.\n    // p(m) = m + m² * P(m). polyEval uses Estrin on CPU (~27% faster),\n    // Horner on GPU (better for in-order pipelines).\n    Flt inner = dispenso::fast_math::polyEval(\n        m,\n        0.0924733654f,\n        -0.14482744f,\n        0.148145974f,\n        -0.165455937f,\n        0.199700251f,\n        -0.250024557f,\n        0.333337069f,\n        -0.499999911f);\n    Flt y = fma_fn(inner, m * m, m); // c0=0, c1=1 absorbed\n\n    y = fma_fn(i, kLn2, y);\n\n    // Add compensation: log1p(x) = log(u) + c/u.\n    Flt result = y + c / u;\n\n    if constexpr (!std::is_same_v<Flt, float>) {\n      // SIMD: blend polynomial for small |x|, compensated log otherwise.\n      auto small = fabs(x) < 0.25f;\n      result = FloatTraits<Flt>::conditional(small, poly_r, result);\n    }\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      // log1p(-1) → -inf, log1p(x < -1) → NaN, log1p(NaN) → NaN.\n      result = detail::logarithmBounds(u, result, xi);\n    }\n\n    return result;\n  }\n}\n\n/**\n * @brief Hyperbolic tangent approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~2 ULP. kBoundsValues: handles NaN.\n * @param x Input value (all float domain).\n * @return tanh(x) in [-1, 1]. Compatible with all SIMD backends.\n *\n * tanh(x) = expm1(2x) / (expm1(2x) + 2).\n * The range-reduced expm1 preserves precision near zero (expm1(2x) ≈ 2x),\n * so this formula naturally gives tanh(x) ≈ x for small x without a\n * separate polynomial. Input clamped to [-10, 10] since tanh(10) = 1.0f\n * exactly in float, and the clamp prevents expm1 overflow for large |x|.\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt tanh(Flt x) {\n  assert_float_type<Flt>();\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return tanh<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar: Sollya fpminimax polynomial for |x| < 1.0 (degree 6 in u = x²).\n    // tanh(x) = x * (1 + u * Q(u)), where Q is fitted to tanh(x)/x - 1.\n    // Error: ~0.52 ULP at the boundary. 6 FMAs.\n    float ax = std::fabs(x);\n    if (!(ax >= 1.0f)) { // !(>=) so NaN enters polynomial path and propagates\n      constexpr float t1 = -0x1.555482p-2f;\n      constexpr float t2 = 0x1.10ef12p-3f;\n      constexpr float t3 = -0x1.b66cecp-5f;\n      constexpr float t4 = 0x1.4e3a6ap-6f;\n      constexpr float t5 = -0x1.9c954p-8f;\n      constexpr float t6 = 0x1.189ec2p-10f;\n      float u = x * x;\n      float poly =\n          std::fma(std::fma(std::fma(std::fma(std::fma(t6, u, t5), u, t4), u, t3), u, t2), u, t1);\n      return x * std::fma(poly, u, 1.0f);\n    }\n    // Large |x|: use expm1 formula (no cancellation, result far from 0).\n    float x_safe = ax < 10.0f ? x : (x < 0.0f ? -10.0f : 10.0f);\n    float em1 = expm1<float, AccuracyTraits>(x_safe + x_safe);\n    return em1 / (em1 + 2.0f);\n  } else {\n    // SIMD: pure expm1 formula (branchless, uniform across all lanes).\n    Flt x_safe = clamp_no_nan(x, Flt(-10.0f), Flt(10.0f));\n    Flt em1 = expm1<Flt, AccuracyTraits>(x_safe + x_safe);\n    Flt result = em1 / (em1 + 2.0f);\n\n    if constexpr (AccuracyTraits::kBoundsValues) {\n      // NaN propagation: clamp_no_nan may map NaN to a finite value.\n      using UintT = UintType_t<Flt>;\n      auto is_nan = (bit_cast<UintT>(x) & UintT(0x7fffffffu)) > UintT(0x7f800000u);\n      result = FloatTraits<Flt>::conditional(is_nan, x, result);\n    }\n\n    return result;\n  }\n}\n\n/**\n * @brief Error function approximation.\n * @tparam Flt float or SIMD float type.\n * @tparam AccuracyTraits Default: ~2 ULP. Not used for bounds (NaN propagates naturally).\n * @param x Input value (all float domain).\n * @return erf(x) in [-1, 1]. Compatible with all SIMD backends.\n *\n * Abramowitz & Stegun 7.1.26-inspired t-substitution with Sollya-optimized\n * coefficients. Uses p=0.45 (vs A&S's 0.3275911) for better polynomial fit.\n *\n * Two domains:\n *   |x| < 0.875:  erf(x) = x * (c0 + x² * Q(x²)),  pure polynomial.\n *   |x| ∈ [0.875, 3.92]:  erf(x) = 1 - t·P(t)·exp(-x²),  t = 1/(1+px).\n *   |x| >= 3.92:  erf(x) = ±1  (saturated in float).\n */\ntemplate <typename Flt, typename AccuracyTraits = DefaultAccuracyTraits>\nDISPENSO_INLINE Flt erf(Flt x) {\n  assert_float_type<Flt>();\n  // AccuracyTraits accepted for API consistency; erf uses the same polynomial for all traits.\n  (void)sizeof(AccuracyTraits);\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return erf<SimdType_t<Flt>, AccuracyTraits>(SimdType_t<Flt>(x)).v;\n  } else if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar path: branching for efficiency.\n    // Save sign and work with |x|; restore sign at end via bit-OR.\n    uint32_t sign = bit_cast<uint32_t>(x) & 0x80000000u;\n    float ax = dispenso::fast_math::fabs(x);\n    float result;\n    if (ax >= 3.92f) {\n      result = 1.0f;\n    } else if (!(ax < 0.875f)) { // !(< ) so NaN goes to erfc path and propagates\n      // erfc formula: erf(x) = 1 - t * P(t) * exp(-x²), t = 1/(1+p*x).\n      constexpr float p = 0.45f;\n      float t = 1.0f / std::fma(p, ax, 1.0f);\n\n      // Sollya fpminimax degree 5 P(t), float coefficients.\n      constexpr float c0 = 0x1.04873ep-2f;\n      constexpr float c1 = 0x1.f81fc6p-3f;\n      constexpr float c2 = 0x1.189f42p-2f;\n      constexpr float c3 = 0x1.15aaa6p-5f;\n      constexpr float c4 = 0x1.65d24ep-2f;\n      constexpr float c5 = -0x1.4432a4p-3f;\n      float poly = t *\n          std::fma(std::fma(std::fma(std::fma(std::fma(c5, t, c4), t, c3), t, c2), t, c1), t, c0);\n\n      // Inline exp(-x²) via Cody-Waite range reduction.\n      float u = ax * ax;\n      constexpr float kLog2e = 0x1.715476p+0f;\n      constexpr float kLn2hi = 0x1.62e400p-1f;\n      constexpr float kLn2lo = 0x1.7f7d1cp-20f;\n      float k = std::floor(u * kLog2e);\n      float f = std::fma(k, -kLn2hi, u);\n      f = std::fma(k, -kLn2lo, f);\n      // Degree-5 Horner for exp(-f), f in [0, ln2).\n      constexpr float e0 = 0x1.fffffep-1f, e1 = -0x1.ffff1ep-1f;\n      constexpr float e2 = 0x1.ffe314p-2f, e3 = -0x1.53f876p-3f;\n      constexpr float e4 = 0x1.462f16p-5f, e5 = -0x1.80e5b2p-8f;\n      float exp_neg_f =\n          std::fma(std::fma(std::fma(std::fma(std::fma(e5, f, e4), f, e3), f, e2), f, e1), f, e0);\n      int32_t ki = convert_to_int_trunc_safe(k);\n      float pow2_neg_k = bit_cast<float>((127 - ki) << 23);\n\n      result = 1.0f - pow2_neg_k * exp_neg_f * poly;\n    } else {\n      // Near-zero: erf(x) = x * (c0 + x² * Q(x²)).\n      // Sollya fpminimax degree 5 Q(u), float coefficients.\n      constexpr float c0 = 0x1.20dd76p+0f; // ≈ 2/√π\n      constexpr float q0 = -0x1.812746p-2f, q1 = 0x1.ce2ec6p-4f, q2 = -0x1.b81edep-6f;\n      constexpr float q3 = 0x1.556b48p-8f, q4 = -0x1.b0255p-11f, q5 = 0x1.7149c8p-14f;\n      float u = ax * ax;\n      float q =\n          std::fma(std::fma(std::fma(std::fma(std::fma(q5, u, q4), u, q3), u, q2), u, q1), u, q0);\n      result = ax * std::fma(q, u, c0);\n    }\n    return bit_cast<float>(bit_cast<uint32_t>(result) | sign);\n  } else {\n    // SIMD: branchless, compute both paths for all lanes and blend.\n    using UintT = UintType_t<Flt>;\n    using IntT = IntType_t<Flt>;\n    auto fma_fn = FloatTraits<Flt>::fma;\n\n    // clamp_allow_nan preserves NaN so it propagates through the computation.\n    Flt ax = clamp_allow_nan(fabs(x), Flt(0.0f), Flt(3.92f));\n\n    // --- Near-zero path: erf(x) = x * (c0 + x² * Q(x²)) ---\n    Flt u_near = ax * ax;\n    constexpr float c0_near = 0x1.20dd76p+0f;\n    Flt q_near = hornerEval(\n        u_near,\n        0x1.7149c8p-14f,\n        -0x1.b0255p-11f,\n        0x1.556b48p-8f,\n        -0x1.b81edep-6f,\n        0x1.ce2ec6p-4f,\n        -0x1.812746p-2f);\n    Flt near_result = ax * fma_fn(q_near, u_near, Flt(c0_near));\n\n    // --- erfc path: erf(x) = 1 - t * P(t) * exp(-x²) ---\n    constexpr float p = 0.45f;\n    Flt denom = fma_fn(Flt(p), ax, Flt(1.0f));\n    Flt t = Flt(1.0f) / denom;\n\n    Flt erfc_poly = t *\n        hornerEval(t,\n                   -0x1.4432a4p-3f,\n                   0x1.65d24ep-2f,\n                   0x1.15aaa6p-5f,\n                   0x1.189f42p-2f,\n                   0x1.f81fc6p-3f,\n                   0x1.04873ep-2f);\n\n    // Inline exp(-x²) via Cody-Waite range reduction.\n    Flt u = ax * ax;\n    constexpr float kLog2e = 0x1.715476p+0f;\n    constexpr float kLn2hi = 0x1.62e400p-1f;\n    constexpr float kLn2lo = 0x1.7f7d1cp-20f;\n    Flt k = floor_small(u * kLog2e);\n    Flt f = fma_fn(k, Flt(-kLn2hi), u);\n    f = fma_fn(k, Flt(-kLn2lo), f);\n    Flt exp_neg_f = hornerEval(\n        f,\n        -0x1.80e5b2p-8f,\n        0x1.462f16p-5f,\n        -0x1.53f876p-3f,\n        0x1.ffe314p-2f,\n        -0x1.ffff1ep-1f,\n        0x1.fffffep-1f);\n    IntT ki = convert_to_int(k);\n    Flt pow2_neg_k = bit_cast<Flt>(UintT((IntT(127) - ki) << 23));\n\n    Flt erfc_result = Flt(1.0f) - pow2_neg_k * exp_neg_f * erfc_poly;\n\n    // Blend: near-zero for |x| < 0.875, erfc otherwise.\n    auto small = ax < Flt(0.875f);\n    Flt result = FloatTraits<Flt>::conditional(small, near_result, erfc_result);\n\n    // Restore sign from original x (odd function). Result is non-negative, so OR stamps sign.\n    result = bit_cast<Flt>(bit_cast<UintT>(result) | (bit_cast<UintT>(x) & UintT(0x80000000u)));\n\n    return result;\n  }\n}\n\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/fast_math/float_traits.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <algorithm>\n#include <cmath>\n#include <cstdint>\n\n#if defined(__SSE__)\n#include <immintrin.h>\n#elif defined(__aarch64__)\n#include <arm_neon.h>\n#endif\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\nnamespace fast_math {\n\n// Float-precision math constants, avoiding repeated static_cast<float>(M_PI) etc.\nconstexpr float kPi = static_cast<float>(M_PI);\nconstexpr float kPi_2 = static_cast<float>(M_PI_2);\nconstexpr float kPi_4 = static_cast<float>(M_PI_4);\nconstexpr float kLn2 = static_cast<float>(M_LN2);\nconstexpr float k1_Ln2 = static_cast<float>(1.0 / M_LN2);\n\ntemplate <typename T>\nstruct FloatTraits {};\n\ntemplate <>\nstruct FloatTraits<float> {\n  using IntType = int32_t;\n  using UintType = uint32_t;\n  using BoolType = bool;\n\n  static constexpr uint32_t kOne = 0x3f800000;\n\n  static constexpr float kMagic = 12582912.f; // 1.5 * 2**23\n\n  static constexpr bool kBoolIsMask = false;\n\n  static DISPENSO_INLINE float sqrt(float x) {\n    return std::sqrt(x);\n  }\n\n  static DISPENSO_INLINE float rcp(float x) {\n#if defined(__SSE__)\n    return _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ss(x)));\n#elif defined(__aarch64__)\n    return vrecpes_f32(x);\n#else\n    return 1.0f / x;\n#endif\n  }\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(bool b, Arg x, Arg y) {\n    return b ? x : y;\n  }\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(bool b, Arg x) {\n    // For kBoolIsMask cases, this is b & x\n    return b * x;\n  }\n\n  static DISPENSO_INLINE float min(float a, float b) {\n    return std::min(a, b);\n  }\n\n  static DISPENSO_INLINE float max(float a, float b) {\n    return std::max(a, b);\n  }\n\n  static DISPENSO_INLINE float fma(float a, float b, float c) {\n    return std::fma(a, b, c);\n  }\n};\n\ntemplate <>\nstruct FloatTraits<int32_t> {\n  using IntType = int32_t;\n};\n\ntemplate <>\nstruct FloatTraits<uint32_t> {\n  using IntType = uint32_t;\n};\n\n// Non-deduced context helper: prevents template argument deduction on a parameter.\n// Use as function parameter type to force callers to rely on deduction from other args.\ntemplate <typename T>\nstruct NonDeducedHelper {\n  using type = T;\n};\ntemplate <typename T>\nusing NonDeduced = typename NonDeducedHelper<T>::type;\n\n// Maps raw SIMD intrinsic types to their wrapper types for template deduction.\n// Default (identity): scalar types and wrapper types map to themselves.\n// Specializations in backend headers map __m128 → SseFloat, __m256 → AvxFloat, etc.\n// This enables fm::sin(__m128_val) to work via automatic forwarding.\ntemplate <typename T>\nstruct SimdTypeFor {\n  using type = T;\n};\ntemplate <typename T>\nusing SimdType_t = typename SimdTypeFor<T>::type;\n\ntemplate <typename Flt>\nusing IntType_t = typename FloatTraits<SimdType_t<Flt>>::IntType;\ntemplate <typename Flt>\nusing UintType_t = typename FloatTraits<SimdType_t<Flt>>::UintType;\n\ntemplate <typename Flt>\nusing BoolType_t = typename FloatTraits<SimdType_t<Flt>>::BoolType;\n\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/fast_math/float_traits_avx.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#if defined(__AVX2__)\n\n#include <immintrin.h>\n\n#include <cstdint>\n\n#include \"float_traits.h\"\n#include \"util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nstruct AvxInt32;\nstruct AvxUint32;\n\n// 8-wide float SIMD wrapper around __m256.\nstruct AvxFloat {\n  __m256 v;\n\n  AvxFloat() = default;\n  AvxFloat(__m256 vec) : v(vec) {}\n  // Implicit broadcast from scalar — required for polynomial constant propagation.\n  AvxFloat(float f) : v(_mm256_set1_ps(f)) {}\n  // Explicit int→float conversion for (Flt)intExpr patterns.\n  explicit AvxFloat(AvxInt32 i);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m256() const {\n    return v;\n  }\n\n  AvxFloat operator-() const {\n    return _mm256_xor_ps(v, _mm256_set1_ps(-0.0f));\n  }\n\n  AvxFloat& operator+=(AvxFloat o) {\n    v = _mm256_add_ps(v, o.v);\n    return *this;\n  }\n  AvxFloat& operator-=(AvxFloat o) {\n    v = _mm256_sub_ps(v, o.v);\n    return *this;\n  }\n  AvxFloat& operator*=(AvxFloat o) {\n    v = _mm256_mul_ps(v, o.v);\n    return *this;\n  }\n  AvxFloat& operator&=(AvxFloat o) {\n    v = _mm256_and_ps(v, o.v);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend AvxFloat operator+(AvxFloat a, AvxFloat b) {\n    return _mm256_add_ps(a.v, b.v);\n  }\n  friend AvxFloat operator-(AvxFloat a, AvxFloat b) {\n    return _mm256_sub_ps(a.v, b.v);\n  }\n  friend AvxFloat operator*(AvxFloat a, AvxFloat b) {\n    return _mm256_mul_ps(a.v, b.v);\n  }\n  friend AvxFloat operator/(AvxFloat a, AvxFloat b) {\n    return _mm256_div_ps(a.v, b.v);\n  }\n\n  // Comparisons return AvxFloat masks (all-ones or all-zeros per lane).\n  friend AvxFloat operator<(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_LT_OQ);\n  }\n  friend AvxFloat operator>(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_GT_OQ);\n  }\n  friend AvxFloat operator<=(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_LE_OQ);\n  }\n  friend AvxFloat operator>=(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_GE_OQ);\n  }\n  friend AvxFloat operator==(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_EQ_OQ);\n  }\n  friend AvxFloat operator!=(AvxFloat a, AvxFloat b) {\n    return _mm256_cmp_ps(a.v, b.v, _CMP_NEQ_UQ);\n  }\n\n  // Logical NOT of a comparison mask.\n  friend AvxFloat operator!(AvxFloat a) {\n    return _mm256_xor_ps(a.v, _mm256_castsi256_ps(_mm256_set1_epi32(-1)));\n  }\n\n  // Bitwise ops on float masks.\n  friend AvxFloat operator&(AvxFloat a, AvxFloat b) {\n    return _mm256_and_ps(a.v, b.v);\n  }\n  friend AvxFloat operator|(AvxFloat a, AvxFloat b) {\n    return _mm256_or_ps(a.v, b.v);\n  }\n  friend AvxFloat operator^(AvxFloat a, AvxFloat b) {\n    return _mm256_xor_ps(a.v, b.v);\n  }\n};\n\n// 8-wide int32 SIMD wrapper around __m256i.\nstruct AvxInt32 {\n  __m256i v;\n\n  AvxInt32() = default;\n  AvxInt32(__m256i vec) : v(vec) {}\n  AvxInt32(int32_t i) : v(_mm256_set1_epi32(i)) {}\n  // Reinterpret from AvxUint32 (no-op on __m256i).\n  AvxInt32(AvxUint32 u);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m256i() const {\n    return v;\n  }\n\n  AvxInt32 operator-() const {\n    return _mm256_sub_epi32(_mm256_setzero_si256(), v);\n  }\n\n  AvxInt32& operator+=(AvxInt32 o) {\n    v = _mm256_add_epi32(v, o.v);\n    return *this;\n  }\n  AvxInt32& operator-=(AvxInt32 o) {\n    v = _mm256_sub_epi32(v, o.v);\n    return *this;\n  }\n  AvxInt32& operator*=(AvxInt32 o) {\n    v = _mm256_mullo_epi32(v, o.v);\n    return *this;\n  }\n  AvxInt32& operator&=(AvxInt32 o) {\n    v = _mm256_and_si256(v, o.v);\n    return *this;\n  }\n  AvxInt32& operator|=(AvxInt32 o) {\n    v = _mm256_or_si256(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  AvxInt32 operator<<(int n) const {\n    return _mm256_slli_epi32(v, n);\n  }\n  AvxInt32 operator>>(int n) const {\n    return _mm256_srai_epi32(v, n); // Arithmetic shift right\n  }\n  AvxInt32& operator<<=(int n) {\n    v = _mm256_slli_epi32(v, n);\n    return *this;\n  }\n  AvxInt32& operator>>=(int n) {\n    v = _mm256_srai_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend AvxInt32 operator+(AvxInt32 a, AvxInt32 b) {\n    return _mm256_add_epi32(a.v, b.v);\n  }\n  friend AvxInt32 operator-(AvxInt32 a, AvxInt32 b) {\n    return _mm256_sub_epi32(a.v, b.v);\n  }\n  friend AvxInt32 operator*(AvxInt32 a, AvxInt32 b) {\n    return _mm256_mullo_epi32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend AvxInt32 operator&(AvxInt32 a, AvxInt32 b) {\n    return _mm256_and_si256(a.v, b.v);\n  }\n  friend AvxInt32 operator|(AvxInt32 a, AvxInt32 b) {\n    return _mm256_or_si256(a.v, b.v);\n  }\n  friend AvxInt32 operator^(AvxInt32 a, AvxInt32 b) {\n    return _mm256_xor_si256(a.v, b.v);\n  }\n\n  friend AvxInt32 operator~(AvxInt32 a) {\n    return _mm256_xor_si256(a.v, _mm256_set1_epi32(-1));\n  }\n\n  // Comparisons return AvxInt32 masks.\n  friend AvxInt32 operator==(AvxInt32 a, AvxInt32 b) {\n    return _mm256_cmpeq_epi32(a.v, b.v);\n  }\n  friend AvxInt32 operator!=(AvxInt32 a, AvxInt32 b) {\n    return _mm256_xor_si256(_mm256_cmpeq_epi32(a.v, b.v), _mm256_set1_epi32(-1));\n  }\n  friend AvxInt32 operator<(AvxInt32 a, AvxInt32 b) {\n    return _mm256_cmpgt_epi32(b.v, a.v); // No _mm256_cmplt_epi32; use swapped cmpgt.\n  }\n  friend AvxInt32 operator>(AvxInt32 a, AvxInt32 b) {\n    return _mm256_cmpgt_epi32(a.v, b.v);\n  }\n\n  friend AvxInt32 operator!(AvxInt32 a) {\n    return _mm256_cmpeq_epi32(a.v, _mm256_setzero_si256());\n  }\n};\n\n// 8-wide uint32 SIMD wrapper around __m256i.\nstruct AvxUint32 {\n  __m256i v;\n\n  AvxUint32() = default;\n  AvxUint32(__m256i vec) : v(vec) {}\n  AvxUint32(uint32_t u) : v(_mm256_set1_epi32(static_cast<int32_t>(u))) {}\n  // Reinterpret from AvxInt32 (no-op on __m256i).\n  AvxUint32(AvxInt32 i) : v(i.v) {}\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m256i() const {\n    return v;\n  }\n\n  AvxUint32& operator+=(AvxUint32 o) {\n    v = _mm256_add_epi32(v, o.v);\n    return *this;\n  }\n  AvxUint32& operator-=(AvxUint32 o) {\n    v = _mm256_sub_epi32(v, o.v);\n    return *this;\n  }\n  AvxUint32& operator*=(AvxUint32 o) {\n    v = _mm256_mullo_epi32(v, o.v);\n    return *this;\n  }\n  AvxUint32& operator&=(AvxUint32 o) {\n    v = _mm256_and_si256(v, o.v);\n    return *this;\n  }\n  AvxUint32& operator|=(AvxUint32 o) {\n    v = _mm256_or_si256(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  AvxUint32 operator<<(int n) const {\n    return _mm256_slli_epi32(v, n);\n  }\n  AvxUint32 operator>>(int n) const {\n    return _mm256_srli_epi32(v, n); // Logical shift right\n  }\n  AvxUint32& operator<<=(int n) {\n    v = _mm256_slli_epi32(v, n);\n    return *this;\n  }\n  AvxUint32& operator>>=(int n) {\n    v = _mm256_srli_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend AvxUint32 operator+(AvxUint32 a, AvxUint32 b) {\n    return _mm256_add_epi32(a.v, b.v);\n  }\n  friend AvxUint32 operator-(AvxUint32 a, AvxUint32 b) {\n    return _mm256_sub_epi32(a.v, b.v);\n  }\n  friend AvxUint32 operator*(AvxUint32 a, AvxUint32 b) {\n    return _mm256_mullo_epi32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend AvxUint32 operator&(AvxUint32 a, AvxUint32 b) {\n    return _mm256_and_si256(a.v, b.v);\n  }\n  friend AvxUint32 operator|(AvxUint32 a, AvxUint32 b) {\n    return _mm256_or_si256(a.v, b.v);\n  }\n  friend AvxUint32 operator^(AvxUint32 a, AvxUint32 b) {\n    return _mm256_xor_si256(a.v, b.v);\n  }\n\n  friend AvxUint32 operator~(AvxUint32 a) {\n    return _mm256_xor_si256(a.v, _mm256_set1_epi32(-1));\n  }\n\n  // Unsigned comparisons need XOR with sign bit to convert to signed domain.\n  friend AvxUint32 operator==(AvxUint32 a, AvxUint32 b) {\n    return _mm256_cmpeq_epi32(a.v, b.v);\n  }\n  friend AvxUint32 operator!=(AvxUint32 a, AvxUint32 b) {\n    return _mm256_xor_si256(_mm256_cmpeq_epi32(a.v, b.v), _mm256_set1_epi32(-1));\n  }\n  friend AvxUint32 operator>(AvxUint32 a, AvxUint32 b) {\n    __m256i bias = _mm256_set1_epi32(static_cast<int32_t>(0x80000000u));\n    return _mm256_cmpgt_epi32(_mm256_xor_si256(a.v, bias), _mm256_xor_si256(b.v, bias));\n  }\n  friend AvxUint32 operator<(AvxUint32 a, AvxUint32 b) {\n    return b > a;\n  }\n\n  friend AvxUint32 operator!(AvxUint32 a) {\n    return _mm256_cmpeq_epi32(a.v, _mm256_setzero_si256());\n  }\n};\n\n// AvxFloat ↔ AvxInt32 conversion.\ninline AvxFloat::AvxFloat(AvxInt32 i) : v(_mm256_cvtepi32_ps(i.v)) {}\n\n// AvxInt32 ↔ AvxUint32 reinterpret (no-op on __m256i).\ninline AvxInt32::AvxInt32(AvxUint32 u) : v(u.v) {}\n\n// Map raw __m256 to AvxFloat for SimdTypeFor.\ntemplate <>\nstruct SimdTypeFor<__m256> {\n  using type = AvxFloat;\n};\n\n// --- bit_cast specializations ---\n\ntemplate <>\ninline AvxInt32 bit_cast<AvxInt32>(const AvxFloat& f) noexcept {\n  return _mm256_castps_si256(f.v);\n}\ntemplate <>\ninline AvxUint32 bit_cast<AvxUint32>(const AvxFloat& f) noexcept {\n  return _mm256_castps_si256(f.v);\n}\ntemplate <>\ninline AvxFloat bit_cast<AvxFloat>(const AvxInt32& i) noexcept {\n  return _mm256_castsi256_ps(i.v);\n}\ntemplate <>\ninline AvxFloat bit_cast<AvxFloat>(const AvxUint32& u) noexcept {\n  return _mm256_castsi256_ps(u.v);\n}\ntemplate <>\ninline AvxInt32 bit_cast<AvxInt32>(const AvxUint32& u) noexcept {\n  return u.v;\n}\ntemplate <>\ninline AvxUint32 bit_cast<AvxUint32>(const AvxInt32& i) noexcept {\n  return i.v;\n}\n\n// --- FloatTraits<AvxFloat> ---\n\ntemplate <>\nstruct FloatTraits<AvxFloat> {\n  using IntType = AvxInt32;\n  using UintType = AvxUint32;\n  using BoolType = AvxFloat; // Float comparison masks\n\n  static constexpr uint32_t kOne = 0x3f800000;\n  static constexpr float kMagic = 12582912.f;\n  static constexpr bool kBoolIsMask = true;\n\n  static DISPENSO_INLINE AvxFloat sqrt(AvxFloat x) {\n    return _mm256_sqrt_ps(x.v);\n  }\n\n  static DISPENSO_INLINE AvxFloat rcp(AvxFloat x) {\n    return _mm256_rcp_ps(x.v);\n  }\n\n  static DISPENSO_INLINE AvxFloat fma(AvxFloat a, AvxFloat b, AvxFloat c) {\n#if defined(__FMA__)\n    return _mm256_fmadd_ps(a.v, b.v, c.v);\n#else\n    return _mm256_add_ps(_mm256_mul_ps(a.v, b.v), c.v);\n#endif\n  }\n\n  // conditional: select x where mask is true, y where false.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(AvxFloat mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(AvxInt32 mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(AvxFloat mask, Arg x);\n\n  static DISPENSO_INLINE AvxFloat min(AvxFloat a, AvxFloat b) {\n    return _mm256_min_ps(a.v, b.v);\n  }\n\n  static DISPENSO_INLINE AvxFloat max(AvxFloat a, AvxFloat b) {\n    return _mm256_max_ps(a.v, b.v);\n  }\n};\n\n// conditional specializations.\ntemplate <>\ninline AvxFloat FloatTraits<AvxFloat>::conditional(AvxFloat mask, AvxFloat x, AvxFloat y) {\n  return _mm256_blendv_ps(y.v, x.v, mask.v);\n}\ntemplate <>\ninline AvxInt32 FloatTraits<AvxFloat>::conditional(AvxFloat mask, AvxInt32 x, AvxInt32 y) {\n  return _mm256_castps_si256(\n      _mm256_blendv_ps(_mm256_castsi256_ps(y.v), _mm256_castsi256_ps(x.v), mask.v));\n}\ntemplate <>\ninline AvxUint32 FloatTraits<AvxFloat>::conditional(AvxFloat mask, AvxUint32 x, AvxUint32 y) {\n  return _mm256_castps_si256(\n      _mm256_blendv_ps(_mm256_castsi256_ps(y.v), _mm256_castsi256_ps(x.v), mask.v));\n}\n\ntemplate <>\ninline AvxFloat FloatTraits<AvxFloat>::conditional(AvxInt32 mask, AvxFloat x, AvxFloat y) {\n  return _mm256_blendv_ps(y.v, x.v, _mm256_castsi256_ps(mask.v));\n}\ntemplate <>\ninline AvxInt32 FloatTraits<AvxFloat>::conditional(AvxInt32 mask, AvxInt32 x, AvxInt32 y) {\n  return _mm256_castps_si256(_mm256_blendv_ps(\n      _mm256_castsi256_ps(y.v), _mm256_castsi256_ps(x.v), _mm256_castsi256_ps(mask.v)));\n}\ntemplate <>\ninline AvxUint32 FloatTraits<AvxFloat>::conditional(AvxInt32 mask, AvxUint32 x, AvxUint32 y) {\n  return _mm256_castps_si256(_mm256_blendv_ps(\n      _mm256_castsi256_ps(y.v), _mm256_castsi256_ps(x.v), _mm256_castsi256_ps(mask.v)));\n}\n\n// apply: mask & x (bitwise AND).\ntemplate <>\ninline AvxFloat FloatTraits<AvxFloat>::apply(AvxFloat mask, AvxFloat x) {\n  return _mm256_and_ps(mask.v, x.v);\n}\ntemplate <>\ninline AvxInt32 FloatTraits<AvxFloat>::apply(AvxFloat mask, AvxInt32 x) {\n  return _mm256_and_si256(_mm256_castps_si256(mask.v), x.v);\n}\ntemplate <>\ninline AvxUint32 FloatTraits<AvxFloat>::apply(AvxFloat mask, AvxUint32 x) {\n  return _mm256_and_si256(_mm256_castps_si256(mask.v), x.v);\n}\n\ntemplate <>\nstruct FloatTraits<AvxInt32> {\n  using IntType = AvxInt32;\n};\n\ntemplate <>\nstruct FloatTraits<AvxUint32> {\n  using IntType = AvxUint32;\n};\n\n// --- Util function overloads for AVX types ---\n\nDISPENSO_INLINE AvxFloat floor_small(AvxFloat x) {\n  return _mm256_floor_ps(x.v);\n}\n\nDISPENSO_INLINE AvxInt32 convert_to_int_trunc(AvxFloat f) {\n  return _mm256_cvttps_epi32(f.v);\n}\n\nDISPENSO_INLINE AvxInt32 convert_to_int_trunc_safe(AvxFloat f) {\n  AvxInt32 fi = bit_cast<AvxInt32>(f);\n  AvxInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & AvxInt32(_mm256_cvttps_epi32(f.v));\n}\n\nDISPENSO_INLINE AvxInt32 convert_to_int(AvxFloat f) {\n  // _mm256_cvtps_epi32 uses round-to-nearest-even.\n  // Mask non-normals to 0 to avoid undefined behavior.\n  AvxInt32 fi = bit_cast<AvxInt32>(f);\n  AvxInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & AvxInt32(_mm256_cvtps_epi32(f.v));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxFloat min<AvxFloat>(AvxFloat x, AvxFloat mn) {\n  // Ordering: if x is NaN, result is mn (second operand).\n  return _mm256_min_ps(x.v, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE AvxFloat clamp_allow_nan<AvxFloat>(AvxFloat x, AvxFloat mn, AvxFloat mx) {\n  return _mm256_max_ps(mn.v, _mm256_min_ps(mx.v, x.v));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxFloat clamp_no_nan<AvxFloat>(AvxFloat x, AvxFloat mn, AvxFloat mx) {\n  return _mm256_max_ps(mn.v, _mm256_min_ps(x.v, mx.v));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxFloat gather<AvxFloat>(const float* table, AvxInt32 index) {\n  return _mm256_i32gather_ps(table, index.v, 4);\n}\n\nDISPENSO_INLINE AvxInt32 int_div_by_3(AvxInt32 i) {\n  // Multiply each lane by 0x55555556 and take the high 32 bits.\n  // Process even and odd lanes separately since _mm256_mul_epu32 only uses lanes 0,2,4,6.\n  __m256i multiplier = _mm256_set1_epi32(0x55555556);\n  // Even lanes (0, 2, 4, 6).\n  __m256i even = _mm256_srli_epi64(_mm256_mul_epu32(i.v, multiplier), 32);\n  // Odd lanes (1, 3, 5, 7): shift right by 32 bits to put odd lanes in even positions.\n  __m256i i_odd = _mm256_srli_epi64(i.v, 32);\n  __m256i odd = _mm256_srli_epi64(_mm256_mul_epu32(i_odd, multiplier), 32);\n  odd = _mm256_slli_epi64(odd, 32);\n  // Blend at 32-bit granularity: even indices from even, odd from odd.\n  return _mm256_blend_epi32(even, odd, 0xAA); // 0xAA = 10101010b\n}\n\n// nonnormal/nonnormalOrZero: return AvxInt32 masks for AVX types.\nDISPENSO_INLINE AvxInt32 nonnormal(AvxInt32 i) {\n  return (i & 0x7f800000) == 0x7f800000;\n}\n\nDISPENSO_INLINE AvxInt32 nonnormalOrZero(AvxInt32 i) {\n  auto m = i & 0x7f800000;\n  return (m == 0x7f800000) | (m == 0);\n}\n\nDISPENSO_INLINE AvxInt32 nonnormal(AvxFloat f) {\n  return nonnormal(bit_cast<AvxInt32>(f));\n}\n\n// any_true: reduce SIMD mask to scalar bool (true if any lane is set).\nDISPENSO_INLINE bool any_true(AvxInt32 mask) {\n  return _mm256_movemask_ps(_mm256_castsi256_ps(mask.v)) != 0;\n}\n\nDISPENSO_INLINE AvxFloat signof(AvxFloat x) {\n  AvxUint32 xi = bit_cast<AvxUint32>(x);\n  return bit_cast<AvxFloat>((xi & 0x80000000u) | FloatTraits<AvxFloat>::kOne);\n}\n\nDISPENSO_INLINE AvxInt32 signofi(AvxInt32 i) {\n  return AvxInt32(1) - (AvxInt32(2) & (i < AvxInt32(0)));\n}\n\n// nbool_as_one: 0 if mask is true (all-ones), 1 if false (all-zeros).\ntemplate <>\nDISPENSO_INLINE AvxFloat nbool_as_one<AvxFloat, AvxFloat>(AvxFloat b) {\n  // ~mask & 1.0f bits\n  return bit_cast<AvxFloat>(\n      AvxInt32(_mm256_andnot_si256(_mm256_castps_si256(b.v), _mm256_set1_epi32(0x3f800000))));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxInt32 nbool_as_one<AvxInt32, AvxFloat>(AvxFloat b) {\n  return _mm256_andnot_si256(_mm256_castps_si256(b.v), _mm256_set1_epi32(1));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxInt32 nbool_as_one<AvxInt32, AvxInt32>(AvxInt32 b) {\n  return _mm256_andnot_si256(b.v, _mm256_set1_epi32(1));\n}\n\n// bool_as_one: 1 if mask is true, 0 if false.\ntemplate <>\nDISPENSO_INLINE AvxFloat bool_as_one<AvxFloat, AvxFloat>(AvxFloat b) {\n  return bit_cast<AvxFloat>(\n      AvxInt32(_mm256_and_si256(_mm256_castps_si256(b.v), _mm256_set1_epi32(0x3f800000))));\n}\n\ntemplate <>\nDISPENSO_INLINE AvxInt32 bool_as_one<AvxInt32, AvxFloat>(AvxFloat b) {\n  return _mm256_and_si256(_mm256_castps_si256(b.v), _mm256_set1_epi32(1));\n}\n\n// bool_as_mask: for SIMD masks, identity (already a mask).\ntemplate <>\nDISPENSO_INLINE AvxInt32 bool_as_mask<AvxInt32, AvxFloat>(AvxFloat b) {\n  return _mm256_castps_si256(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE AvxInt32 bool_as_mask<AvxInt32, AvxInt32>(AvxInt32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE AvxInt32 bool_as_mask<AvxInt32, AvxUint32>(AvxUint32 b) {\n  return b.v;\n}\n\ntemplate <>\nDISPENSO_INLINE AvxUint32 bool_as_mask<AvxUint32, AvxFloat>(AvxFloat b) {\n  return _mm256_castps_si256(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE AvxUint32 bool_as_mask<AvxUint32, AvxUint32>(AvxUint32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE AvxUint32 bool_as_mask<AvxUint32, AvxInt32>(AvxInt32 b) {\n  return b.v;\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n#endif // defined(__AVX2__)\n"
  },
  {
    "path": "dispenso/fast_math/float_traits_avx512.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#if defined(__AVX512F__)\n\n#include <immintrin.h>\n\n#include <cstdint>\n\n#include \"float_traits.h\"\n#include \"util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nstruct Avx512Int32;\nstruct Avx512Uint32;\n\n// 16-bit mask wrapping __mmask16 for AVX-512 predicated operations.\n// Supports comparison with int literals (mask == 0 → all-false check),\n// logical ops, and implicit conversion to Avx512Int32 for template code\n// that assigns BoolType to IntType.\nstruct Avx512Mask {\n  __mmask16 m;\n\n  Avx512Mask() = default;\n  Avx512Mask(__mmask16 mask) : m(mask) {}\n  // Construct from int literal: 0 → all-false, non-zero → all-true.\n  // Used by template code like `(expr) == 0` where expr is BoolType.\n  Avx512Mask(int val) : m(val ? 0xFFFF : 0) {}\n\n  // Logical NOT.\n  friend Avx512Mask operator!(Avx512Mask a) {\n    return static_cast<__mmask16>(~a.m);\n  }\n\n  // Logical AND/OR/XOR.\n  friend Avx512Mask operator&(Avx512Mask a, Avx512Mask b) {\n    return static_cast<__mmask16>(a.m & b.m);\n  }\n  friend Avx512Mask operator|(Avx512Mask a, Avx512Mask b) {\n    return static_cast<__mmask16>(a.m | b.m);\n  }\n  friend Avx512Mask operator^(Avx512Mask a, Avx512Mask b) {\n    return static_cast<__mmask16>(a.m ^ b.m);\n  }\n\n  Avx512Mask& operator&=(Avx512Mask o) {\n    m &= o.m;\n    return *this;\n  }\n  Avx512Mask& operator|=(Avx512Mask o) {\n    m |= o.m;\n    return *this;\n  }\n\n  // Equality: per-bit XNOR. mask == Avx512Mask(0) is equivalent to !mask.\n  friend Avx512Mask operator==(Avx512Mask a, Avx512Mask b) {\n    return static_cast<__mmask16>(~(a.m ^ b.m));\n  }\n  friend Avx512Mask operator!=(Avx512Mask a, Avx512Mask b) {\n    return static_cast<__mmask16>(a.m ^ b.m);\n  }\n\n  // Implicit conversion to Avx512Int32 (lane-wide mask: all-ones or all-zeros).\n  // Used by template code that assigns BoolType to IntType_t<Flt>.\n  inline operator Avx512Int32() const;\n};\n\n// 16-wide float SIMD wrapper around __m512.\nstruct Avx512Float {\n  __m512 v;\n\n  Avx512Float() = default;\n  Avx512Float(__m512 vec) : v(vec) {}\n  // Implicit broadcast from scalar — required for polynomial constant propagation.\n  Avx512Float(float f) : v(_mm512_set1_ps(f)) {}\n  // Explicit int→float conversion for (Flt)intExpr patterns.\n  explicit Avx512Float(Avx512Int32 i);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m512() const {\n    return v;\n  }\n\n  Avx512Float operator-() const {\n    // _mm512_xor_ps requires AVX-512 DQ; use integer XOR on sign bit instead.\n    return _mm512_castsi512_ps(\n        _mm512_xor_si512(_mm512_castps_si512(v), _mm512_set1_epi32(int32_t(0x80000000))));\n  }\n\n  Avx512Float& operator+=(Avx512Float o) {\n    v = _mm512_add_ps(v, o.v);\n    return *this;\n  }\n  Avx512Float& operator-=(Avx512Float o) {\n    v = _mm512_sub_ps(v, o.v);\n    return *this;\n  }\n  Avx512Float& operator*=(Avx512Float o) {\n    v = _mm512_mul_ps(v, o.v);\n    return *this;\n  }\n  Avx512Float& operator&=(Avx512Float o) {\n    // _mm512_and_ps requires AVX-512 DQ; use integer AND instead.\n    v = _mm512_castsi512_ps(_mm512_and_si512(_mm512_castps_si512(v), _mm512_castps_si512(o.v)));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend Avx512Float operator+(Avx512Float a, Avx512Float b) {\n    return _mm512_add_ps(a.v, b.v);\n  }\n  friend Avx512Float operator-(Avx512Float a, Avx512Float b) {\n    return _mm512_sub_ps(a.v, b.v);\n  }\n  friend Avx512Float operator*(Avx512Float a, Avx512Float b) {\n    return _mm512_mul_ps(a.v, b.v);\n  }\n  friend Avx512Float operator/(Avx512Float a, Avx512Float b) {\n    return _mm512_div_ps(a.v, b.v);\n  }\n\n  // Comparisons return Avx512Mask (native __mmask16).\n  friend Avx512Mask operator<(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_LT_OQ);\n  }\n  friend Avx512Mask operator>(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_GT_OQ);\n  }\n  friend Avx512Mask operator<=(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_LE_OQ);\n  }\n  friend Avx512Mask operator>=(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_GE_OQ);\n  }\n  friend Avx512Mask operator==(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_EQ_OQ);\n  }\n  friend Avx512Mask operator!=(Avx512Float a, Avx512Float b) {\n    return _mm512_cmp_ps_mask(a.v, b.v, _CMP_NEQ_UQ);\n  }\n\n  // Bitwise ops on float values (for sign manipulation, etc.).\n  // _mm512_{and,or,xor}_ps require AVX-512 DQ; use integer ops + casts.\n  friend Avx512Float operator&(Avx512Float a, Avx512Float b) {\n    return _mm512_castsi512_ps(\n        _mm512_and_si512(_mm512_castps_si512(a.v), _mm512_castps_si512(b.v)));\n  }\n  friend Avx512Float operator|(Avx512Float a, Avx512Float b) {\n    return _mm512_castsi512_ps(_mm512_or_si512(_mm512_castps_si512(a.v), _mm512_castps_si512(b.v)));\n  }\n  friend Avx512Float operator^(Avx512Float a, Avx512Float b) {\n    return _mm512_castsi512_ps(\n        _mm512_xor_si512(_mm512_castps_si512(a.v), _mm512_castps_si512(b.v)));\n  }\n};\n\n// 16-wide int32 SIMD wrapper around __m512i.\nstruct Avx512Int32 {\n  __m512i v;\n\n  Avx512Int32() = default;\n  Avx512Int32(__m512i vec) : v(vec) {}\n  Avx512Int32(int32_t i) : v(_mm512_set1_epi32(i)) {}\n  // Reinterpret from Avx512Uint32 (no-op on __m512i).\n  Avx512Int32(Avx512Uint32 u);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m512i() const {\n    return v;\n  }\n\n  Avx512Int32 operator-() const {\n    return _mm512_sub_epi32(_mm512_setzero_si512(), v);\n  }\n\n  Avx512Int32& operator+=(Avx512Int32 o) {\n    v = _mm512_add_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Int32& operator-=(Avx512Int32 o) {\n    v = _mm512_sub_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Int32& operator*=(Avx512Int32 o) {\n    v = _mm512_mullo_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Int32& operator&=(Avx512Int32 o) {\n    v = _mm512_and_si512(v, o.v);\n    return *this;\n  }\n  Avx512Int32& operator|=(Avx512Int32 o) {\n    v = _mm512_or_si512(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  Avx512Int32 operator<<(int n) const {\n    return _mm512_slli_epi32(v, n);\n  }\n  Avx512Int32 operator>>(int n) const {\n    return _mm512_srai_epi32(v, n); // Arithmetic shift right\n  }\n  Avx512Int32& operator<<=(int n) {\n    v = _mm512_slli_epi32(v, n);\n    return *this;\n  }\n  Avx512Int32& operator>>=(int n) {\n    v = _mm512_srai_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend Avx512Int32 operator+(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_add_epi32(a.v, b.v);\n  }\n  friend Avx512Int32 operator-(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_sub_epi32(a.v, b.v);\n  }\n  friend Avx512Int32 operator*(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_mullo_epi32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend Avx512Int32 operator&(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_and_si512(a.v, b.v);\n  }\n  friend Avx512Int32 operator|(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_or_si512(a.v, b.v);\n  }\n  friend Avx512Int32 operator^(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_xor_si512(a.v, b.v);\n  }\n\n  friend Avx512Int32 operator~(Avx512Int32 a) {\n    return _mm512_xor_si512(a.v, _mm512_set1_epi32(-1));\n  }\n\n  // Comparisons return Avx512Mask (native __mmask16).\n  friend Avx512Mask operator==(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_cmpeq_epi32_mask(a.v, b.v);\n  }\n  friend Avx512Mask operator!=(Avx512Int32 a, Avx512Int32 b) {\n    return static_cast<__mmask16>(~_mm512_cmpeq_epi32_mask(a.v, b.v));\n  }\n  friend Avx512Mask operator<(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_cmplt_epi32_mask(a.v, b.v);\n  }\n  friend Avx512Mask operator>(Avx512Int32 a, Avx512Int32 b) {\n    return _mm512_cmpgt_epi32_mask(a.v, b.v);\n  }\n\n  friend Avx512Mask operator!(Avx512Int32 a) {\n    return _mm512_cmpeq_epi32_mask(a.v, _mm512_setzero_si512());\n  }\n};\n\n// 16-wide uint32 SIMD wrapper around __m512i.\nstruct Avx512Uint32 {\n  __m512i v;\n\n  Avx512Uint32() = default;\n  Avx512Uint32(__m512i vec) : v(vec) {}\n  Avx512Uint32(uint32_t u) : v(_mm512_set1_epi32(static_cast<int32_t>(u))) {}\n  // Reinterpret from Avx512Int32 (no-op on __m512i).\n  Avx512Uint32(Avx512Int32 i) : v(i.v) {}\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m512i() const {\n    return v;\n  }\n\n  Avx512Uint32& operator+=(Avx512Uint32 o) {\n    v = _mm512_add_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Uint32& operator-=(Avx512Uint32 o) {\n    v = _mm512_sub_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Uint32& operator*=(Avx512Uint32 o) {\n    v = _mm512_mullo_epi32(v, o.v);\n    return *this;\n  }\n  Avx512Uint32& operator&=(Avx512Uint32 o) {\n    v = _mm512_and_si512(v, o.v);\n    return *this;\n  }\n  Avx512Uint32& operator|=(Avx512Uint32 o) {\n    v = _mm512_or_si512(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  Avx512Uint32 operator<<(int n) const {\n    return _mm512_slli_epi32(v, n);\n  }\n  Avx512Uint32 operator>>(int n) const {\n    return _mm512_srli_epi32(v, n); // Logical shift right\n  }\n  Avx512Uint32& operator<<=(int n) {\n    v = _mm512_slli_epi32(v, n);\n    return *this;\n  }\n  Avx512Uint32& operator>>=(int n) {\n    v = _mm512_srli_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend Avx512Uint32 operator+(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_add_epi32(a.v, b.v);\n  }\n  friend Avx512Uint32 operator-(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_sub_epi32(a.v, b.v);\n  }\n  friend Avx512Uint32 operator*(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_mullo_epi32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend Avx512Uint32 operator&(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_and_si512(a.v, b.v);\n  }\n  friend Avx512Uint32 operator|(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_or_si512(a.v, b.v);\n  }\n  friend Avx512Uint32 operator^(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_xor_si512(a.v, b.v);\n  }\n\n  friend Avx512Uint32 operator~(Avx512Uint32 a) {\n    return _mm512_xor_si512(a.v, _mm512_set1_epi32(-1));\n  }\n\n  // AVX-512 has native unsigned comparisons.\n  friend Avx512Mask operator==(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_cmpeq_epi32_mask(a.v, b.v);\n  }\n  friend Avx512Mask operator!=(Avx512Uint32 a, Avx512Uint32 b) {\n    return static_cast<__mmask16>(~_mm512_cmpeq_epi32_mask(a.v, b.v));\n  }\n  friend Avx512Mask operator>(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_cmpgt_epu32_mask(a.v, b.v);\n  }\n  friend Avx512Mask operator<(Avx512Uint32 a, Avx512Uint32 b) {\n    return _mm512_cmplt_epu32_mask(a.v, b.v);\n  }\n\n  friend Avx512Mask operator!(Avx512Uint32 a) {\n    return _mm512_cmpeq_epi32_mask(a.v, _mm512_setzero_si512());\n  }\n};\n\n// --- Deferred inline definitions ---\n\n// Avx512Mask → Avx512Int32: expand to lane-wide mask (all-ones or all-zeros).\ninline Avx512Mask::operator Avx512Int32() const {\n  return _mm512_maskz_set1_epi32(m, -1);\n}\n\n// Avx512Float ↔ Avx512Int32 conversion.\ninline Avx512Float::Avx512Float(Avx512Int32 i) : v(_mm512_cvtepi32_ps(i.v)) {}\n\n// Avx512Int32 ↔ Avx512Uint32 reinterpret (no-op on __m512i).\ninline Avx512Int32::Avx512Int32(Avx512Uint32 u) : v(u.v) {}\n\n// Map raw __m512 to Avx512Float for SimdTypeFor.\ntemplate <>\nstruct SimdTypeFor<__m512> {\n  using type = Avx512Float;\n};\n\n// --- bit_cast specializations ---\n\ntemplate <>\ninline Avx512Int32 bit_cast<Avx512Int32>(const Avx512Float& f) noexcept {\n  return _mm512_castps_si512(f.v);\n}\ntemplate <>\ninline Avx512Uint32 bit_cast<Avx512Uint32>(const Avx512Float& f) noexcept {\n  return _mm512_castps_si512(f.v);\n}\ntemplate <>\ninline Avx512Float bit_cast<Avx512Float>(const Avx512Int32& i) noexcept {\n  return _mm512_castsi512_ps(i.v);\n}\ntemplate <>\ninline Avx512Float bit_cast<Avx512Float>(const Avx512Uint32& u) noexcept {\n  return _mm512_castsi512_ps(u.v);\n}\ntemplate <>\ninline Avx512Int32 bit_cast<Avx512Int32>(const Avx512Uint32& u) noexcept {\n  return u.v;\n}\ntemplate <>\ninline Avx512Uint32 bit_cast<Avx512Uint32>(const Avx512Int32& i) noexcept {\n  return i.v;\n}\n\n// --- FloatTraits<Avx512Float> ---\n\ntemplate <>\nstruct FloatTraits<Avx512Float> {\n  using IntType = Avx512Int32;\n  using UintType = Avx512Uint32;\n  using BoolType = Avx512Mask;\n\n  static constexpr uint32_t kOne = 0x3f800000;\n  static constexpr float kMagic = 12582912.f;\n  static constexpr bool kBoolIsMask = true;\n\n  static DISPENSO_INLINE Avx512Float sqrt(Avx512Float x) {\n    return _mm512_sqrt_ps(x.v);\n  }\n\n  static DISPENSO_INLINE Avx512Float rcp(Avx512Float x) {\n    return _mm512_rcp14_ps(x.v);\n  }\n\n  // AVX-512 always has FMA.\n  static DISPENSO_INLINE Avx512Float fma(Avx512Float a, Avx512Float b, Avx512Float c) {\n    return _mm512_fmadd_ps(a.v, b.v, c.v);\n  }\n\n  // conditional: select x where mask is true, y where false.\n  // Native __mmask16 versions — the fast path.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(Avx512Mask mask, Arg x, Arg y);\n\n  // Lane-wide int32 mask versions — for compatibility with code using IntType masks.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(Avx512Int32 mask, Arg x, Arg y);\n\n  // apply: zero out lanes where mask is false.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(Avx512Mask mask, Arg x);\n\n  static DISPENSO_INLINE Avx512Float min(Avx512Float a, Avx512Float b) {\n    return _mm512_min_ps(a.v, b.v);\n  }\n\n  static DISPENSO_INLINE Avx512Float max(Avx512Float a, Avx512Float b) {\n    return _mm512_max_ps(a.v, b.v);\n  }\n};\n\n// conditional specializations (Avx512Mask).\ntemplate <>\ninline Avx512Float\nFloatTraits<Avx512Float>::conditional(Avx512Mask mask, Avx512Float x, Avx512Float y) {\n  return _mm512_mask_blend_ps(mask.m, y.v, x.v);\n}\ntemplate <>\ninline Avx512Int32\nFloatTraits<Avx512Float>::conditional(Avx512Mask mask, Avx512Int32 x, Avx512Int32 y) {\n  return _mm512_mask_blend_epi32(mask.m, y.v, x.v);\n}\ntemplate <>\ninline Avx512Uint32\nFloatTraits<Avx512Float>::conditional(Avx512Mask mask, Avx512Uint32 x, Avx512Uint32 y) {\n  return _mm512_mask_blend_epi32(mask.m, y.v, x.v);\n}\n\n// conditional specializations (Avx512Int32 lane-wide mask).\n// Convert lane-wide mask to __mmask16 by checking sign bit (equivalent to movepi32_mask,\n// which requires AVX-512 DQ).\ntemplate <>\ninline Avx512Float\nFloatTraits<Avx512Float>::conditional(Avx512Int32 mask, Avx512Float x, Avx512Float y) {\n  __mmask16 m = _mm512_cmplt_epi32_mask(mask.v, _mm512_setzero_si512());\n  return _mm512_mask_blend_ps(m, y.v, x.v);\n}\ntemplate <>\ninline Avx512Int32\nFloatTraits<Avx512Float>::conditional(Avx512Int32 mask, Avx512Int32 x, Avx512Int32 y) {\n  __mmask16 m = _mm512_cmplt_epi32_mask(mask.v, _mm512_setzero_si512());\n  return _mm512_mask_blend_epi32(m, y.v, x.v);\n}\ntemplate <>\ninline Avx512Uint32\nFloatTraits<Avx512Float>::conditional(Avx512Int32 mask, Avx512Uint32 x, Avx512Uint32 y) {\n  __mmask16 m = _mm512_cmplt_epi32_mask(mask.v, _mm512_setzero_si512());\n  return _mm512_mask_blend_epi32(m, y.v, x.v);\n}\n\n// apply specializations (Avx512Mask): zero out lanes where mask is false.\ntemplate <>\ninline Avx512Float FloatTraits<Avx512Float>::apply(Avx512Mask mask, Avx512Float x) {\n  return _mm512_maskz_mov_ps(mask.m, x.v);\n}\ntemplate <>\ninline Avx512Int32 FloatTraits<Avx512Float>::apply(Avx512Mask mask, Avx512Int32 x) {\n  return _mm512_maskz_mov_epi32(mask.m, x.v);\n}\ntemplate <>\ninline Avx512Uint32 FloatTraits<Avx512Float>::apply(Avx512Mask mask, Avx512Uint32 x) {\n  return _mm512_maskz_mov_epi32(mask.m, x.v);\n}\n\ntemplate <>\nstruct FloatTraits<Avx512Int32> {\n  using IntType = Avx512Int32;\n};\n\ntemplate <>\nstruct FloatTraits<Avx512Uint32> {\n  using IntType = Avx512Uint32;\n};\n\n// --- Util function overloads for AVX-512 types ---\n\nDISPENSO_INLINE Avx512Float floor_small(Avx512Float x) {\n  return _mm512_floor_ps(x.v);\n}\n\nDISPENSO_INLINE Avx512Int32 convert_to_int_trunc(Avx512Float f) {\n  return _mm512_cvttps_epi32(f.v);\n}\n\nDISPENSO_INLINE Avx512Int32 convert_to_int_trunc_safe(Avx512Float f) {\n  Avx512Int32 fi = bit_cast<Avx512Int32>(f);\n  __mmask16 norm = static_cast<__mmask16>(~_mm512_cmpeq_epi32_mask(\n      _mm512_and_si512(fi.v, _mm512_set1_epi32(0x7f800000)), _mm512_set1_epi32(0x7f800000)));\n  return _mm512_maskz_cvttps_epi32(norm, f.v);\n}\n\nDISPENSO_INLINE Avx512Int32 convert_to_int(Avx512Float f) {\n  // _mm512_cvtps_epi32 uses round-to-nearest-even.\n  // Use maskz to zero non-normal lanes and avoid undefined behavior.\n  Avx512Int32 fi = bit_cast<Avx512Int32>(f);\n  __mmask16 norm = static_cast<__mmask16>(~_mm512_cmpeq_epi32_mask(\n      _mm512_and_si512(fi.v, _mm512_set1_epi32(0x7f800000)), _mm512_set1_epi32(0x7f800000)));\n  return _mm512_maskz_cvtps_epi32(norm, f.v);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Float min<Avx512Float>(Avx512Float x, Avx512Float mn) {\n  // Ordering: if x is NaN, result is mn (second operand).\n  return _mm512_min_ps(x.v, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Float\nclamp_allow_nan<Avx512Float>(Avx512Float x, Avx512Float mn, Avx512Float mx) {\n  return _mm512_max_ps(mn.v, _mm512_min_ps(mx.v, x.v));\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Float\nclamp_no_nan<Avx512Float>(Avx512Float x, Avx512Float mn, Avx512Float mx) {\n  return _mm512_max_ps(mn.v, _mm512_min_ps(x.v, mx.v));\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Float gather<Avx512Float>(const float* table, Avx512Int32 index) {\n  // Note: AVX-512 gather has index as first arg, base as second.\n  return _mm512_i32gather_ps(index.v, table, 4);\n}\n\nDISPENSO_INLINE Avx512Int32 int_div_by_3(Avx512Int32 i) {\n  // Multiply each lane by 0x55555556 and take the high 32 bits.\n  // Process even and odd lanes separately since _mm512_mul_epu32 only uses lanes 0,2,...\n  __m512i multiplier = _mm512_set1_epi32(0x55555556);\n  // Even lanes (0, 2, 4, ..., 14).\n  __m512i even = _mm512_srli_epi64(_mm512_mul_epu32(i.v, multiplier), 32);\n  // Odd lanes (1, 3, 5, ..., 15): shift right by 32 to put odd in even positions.\n  __m512i i_odd = _mm512_srli_epi64(i.v, 32);\n  __m512i odd = _mm512_srli_epi64(_mm512_mul_epu32(i_odd, multiplier), 32);\n  odd = _mm512_slli_epi64(odd, 32);\n  // Blend at 32-bit granularity: even indices from even, odd from odd.\n  return _mm512_mask_blend_epi32(0xAAAA, even, odd); // 0xAAAA = odd lanes from 'odd'\n}\n\n// nonnormal/nonnormalOrZero: return Avx512Mask for AVX-512 types.\nDISPENSO_INLINE Avx512Mask nonnormal(Avx512Int32 i) {\n  return _mm512_cmpeq_epi32_mask(\n      _mm512_and_si512(i.v, _mm512_set1_epi32(0x7f800000)), _mm512_set1_epi32(0x7f800000));\n}\n\nDISPENSO_INLINE Avx512Mask nonnormalOrZero(Avx512Int32 i) {\n  __m512i masked = _mm512_and_si512(i.v, _mm512_set1_epi32(0x7f800000));\n  __mmask16 isInfNan = _mm512_cmpeq_epi32_mask(masked, _mm512_set1_epi32(0x7f800000));\n  __mmask16 isZero = _mm512_cmpeq_epi32_mask(masked, _mm512_setzero_si512());\n  return static_cast<__mmask16>(isInfNan | isZero);\n}\n\nDISPENSO_INLINE Avx512Mask nonnormal(Avx512Float f) {\n  return nonnormal(bit_cast<Avx512Int32>(f));\n}\n\n// any_true: reduce mask to scalar bool (Avx512Mask wraps __mmask16).\nDISPENSO_INLINE bool any_true(Avx512Mask mask) {\n  return mask.m != 0;\n}\n\nDISPENSO_INLINE Avx512Float signof(Avx512Float x) {\n  Avx512Uint32 xi = bit_cast<Avx512Uint32>(x);\n  return bit_cast<Avx512Float>((xi & 0x80000000u) | FloatTraits<Avx512Float>::kOne);\n}\n\nDISPENSO_INLINE Avx512Int32 signofi(Avx512Int32 i) {\n  // Use mask blend: +1 for i >= 0, -1 for i < 0.\n  __mmask16 neg = _mm512_cmplt_epi32_mask(i.v, _mm512_setzero_si512());\n  return _mm512_mask_blend_epi32(neg, _mm512_set1_epi32(1), _mm512_set1_epi32(-1));\n}\n\n// nbool_as_one: 0 if mask is true, 1 if false.\ntemplate <>\nDISPENSO_INLINE Avx512Float nbool_as_one<Avx512Float, Avx512Mask>(Avx512Mask b) {\n  // Where mask is false (0 in mask bit), load 1.0f; where true, load 0.\n  return _mm512_maskz_mov_ps(static_cast<__mmask16>(~b.m), _mm512_set1_ps(1.0f));\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32 nbool_as_one<Avx512Int32, Avx512Mask>(Avx512Mask b) {\n  return _mm512_maskz_set1_epi32(static_cast<__mmask16>(~b.m), 1);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32 nbool_as_one<Avx512Int32, Avx512Int32>(Avx512Int32 b) {\n  // Lane-wide mask: non-zero → \"true\" → return 0; zero → \"false\" → return 1.\n  __mmask16 isZero = _mm512_cmpeq_epi32_mask(b.v, _mm512_setzero_si512());\n  return _mm512_maskz_set1_epi32(isZero, 1);\n}\n\n// bool_as_one: 1 if mask is true, 0 if false.\ntemplate <>\nDISPENSO_INLINE Avx512Float bool_as_one<Avx512Float, Avx512Mask>(Avx512Mask b) {\n  return _mm512_maskz_mov_ps(b.m, _mm512_set1_ps(1.0f));\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32 bool_as_one<Avx512Int32, Avx512Mask>(Avx512Mask b) {\n  return _mm512_maskz_set1_epi32(b.m, 1);\n}\n\n// bool_as_mask: convert Avx512Mask to lane-wide Avx512Int32 mask.\ntemplate <>\nDISPENSO_INLINE Avx512Int32 bool_as_mask<Avx512Int32, Avx512Mask>(Avx512Mask b) {\n  return _mm512_maskz_set1_epi32(b.m, -1);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32 bool_as_mask<Avx512Int32, Avx512Int32>(Avx512Int32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32 bool_as_mask<Avx512Int32, Avx512Uint32>(Avx512Uint32 b) {\n  return b.v;\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Uint32 bool_as_mask<Avx512Uint32, Avx512Mask>(Avx512Mask b) {\n  return _mm512_maskz_set1_epi32(b.m, -1);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Uint32 bool_as_mask<Avx512Uint32, Avx512Uint32>(Avx512Uint32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Uint32 bool_as_mask<Avx512Uint32, Avx512Int32>(Avx512Int32 b) {\n  return b.v;\n}\n\n// bool_apply_or_zero: specialized for Avx512Mask to use native masked operations.\ntemplate <>\nDISPENSO_INLINE Avx512Float\nbool_apply_or_zero<Avx512Float, Avx512Mask>(Avx512Mask b, Avx512Float val) {\n  return _mm512_maskz_mov_ps(b.m, val.v);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Int32\nbool_apply_or_zero<Avx512Int32, Avx512Mask>(Avx512Mask b, Avx512Int32 val) {\n  return _mm512_maskz_mov_epi32(b.m, val.v);\n}\n\ntemplate <>\nDISPENSO_INLINE Avx512Uint32\nbool_apply_or_zero<Avx512Uint32, Avx512Mask>(Avx512Mask b, Avx512Uint32 val) {\n  return _mm512_maskz_mov_epi32(b.m, val.v);\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n#endif // defined(__AVX512F__)\n"
  },
  {
    "path": "dispenso/fast_math/float_traits_hwy.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n// Only include when Highway is available on the include path.\n// Consumers must depend on the Highway library target.\n#if __has_include(\"hwy/highway.h\")\n\n#include \"hwy/highway.h\"\n\n#include <cstdint>\n\n#include \"float_traits.h\"\n#include \"util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nnamespace hn = hwy::HWY_NAMESPACE;\n\nusing HwyFloatTag = hn::ScalableTag<float>;\nusing HwyInt32Tag = hn::RebindToSigned<HwyFloatTag>;\nusing HwyUint32Tag = hn::RebindToUnsigned<HwyFloatTag>;\n\nstruct HwyInt32;\nstruct HwyUint32;\n\n// N-wide float SIMD wrapper around Highway Vec<ScalableTag<float>>.\n// Width is determined at compile time by Highway's static dispatch.\nstruct HwyFloat {\n  hn::Vec<HwyFloatTag> v;\n\n  HwyFloat() = default;\n  HwyFloat(hn::Vec<HwyFloatTag> vec) : v(vec) {}\n  // Implicit broadcast from scalar — required for polynomial constant propagation.\n  HwyFloat(float f) : v(hn::Set(HwyFloatTag{}, f)) {}\n  // Explicit int→float conversion for (Flt)intExpr patterns.\n  explicit HwyFloat(HwyInt32 i);\n\n  HwyFloat operator-() const {\n    return hn::Neg(v);\n  }\n\n  HwyFloat& operator+=(HwyFloat o) {\n    v = hn::Add(v, o.v);\n    return *this;\n  }\n  HwyFloat& operator-=(HwyFloat o) {\n    v = hn::Sub(v, o.v);\n    return *this;\n  }\n  HwyFloat& operator*=(HwyFloat o) {\n    v = hn::Mul(v, o.v);\n    return *this;\n  }\n  HwyFloat& operator&=(HwyFloat o) {\n    const HwyInt32Tag di;\n    v = hn::BitCast(HwyFloatTag{}, hn::And(hn::BitCast(di, v), hn::BitCast(di, o.v)));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend HwyFloat operator+(HwyFloat a, HwyFloat b) {\n    return hn::Add(a.v, b.v);\n  }\n  friend HwyFloat operator-(HwyFloat a, HwyFloat b) {\n    return hn::Sub(a.v, b.v);\n  }\n  friend HwyFloat operator*(HwyFloat a, HwyFloat b) {\n    return hn::Mul(a.v, b.v);\n  }\n  friend HwyFloat operator/(HwyFloat a, HwyFloat b) {\n    return hn::Div(a.v, b.v);\n  }\n\n  // Comparisons return HwyFloat masks (all-ones or all-zeros per lane).\n  friend HwyFloat operator<(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Lt(a.v, b.v));\n  }\n  friend HwyFloat operator>(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Gt(a.v, b.v));\n  }\n  friend HwyFloat operator<=(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Le(a.v, b.v));\n  }\n  friend HwyFloat operator>=(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Ge(a.v, b.v));\n  }\n  friend HwyFloat operator==(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Eq(a.v, b.v));\n  }\n  friend HwyFloat operator!=(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    return hn::VecFromMask(d, hn::Ne(a.v, b.v));\n  }\n\n  // Logical NOT of a comparison mask.\n  friend HwyFloat operator!(HwyFloat a) {\n    const HwyFloatTag d;\n    const HwyInt32Tag di;\n    return hn::BitCast(d, hn::Xor(hn::BitCast(di, a.v), hn::Set(di, -1)));\n  }\n\n  // Bitwise ops on float masks.\n  friend HwyFloat operator&(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    const HwyInt32Tag di;\n    return hn::BitCast(d, hn::And(hn::BitCast(di, a.v), hn::BitCast(di, b.v)));\n  }\n  friend HwyFloat operator|(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    const HwyInt32Tag di;\n    return hn::BitCast(d, hn::Or(hn::BitCast(di, a.v), hn::BitCast(di, b.v)));\n  }\n  friend HwyFloat operator^(HwyFloat a, HwyFloat b) {\n    const HwyFloatTag d;\n    const HwyInt32Tag di;\n    return hn::BitCast(d, hn::Xor(hn::BitCast(di, a.v), hn::BitCast(di, b.v)));\n  }\n};\n\n// N-wide int32 SIMD wrapper around Highway Vec<RebindToSigned<ScalableTag<float>>>.\nstruct HwyInt32 {\n  hn::Vec<HwyInt32Tag> v;\n\n  HwyInt32() = default;\n  HwyInt32(hn::Vec<HwyInt32Tag> vec) : v(vec) {}\n  HwyInt32(int32_t i) : v(hn::Set(HwyInt32Tag{}, i)) {}\n  // Reinterpret from HwyUint32 (no-op).\n  HwyInt32(HwyUint32 u);\n\n  HwyInt32 operator-() const {\n    return hn::Neg(v);\n  }\n\n  HwyInt32& operator+=(HwyInt32 o) {\n    v = hn::Add(v, o.v);\n    return *this;\n  }\n  HwyInt32& operator-=(HwyInt32 o) {\n    v = hn::Sub(v, o.v);\n    return *this;\n  }\n  HwyInt32& operator*=(HwyInt32 o) {\n    v = hn::Mul(v, o.v);\n    return *this;\n  }\n  HwyInt32& operator&=(HwyInt32 o) {\n    v = hn::And(v, o.v);\n    return *this;\n  }\n  HwyInt32& operator|=(HwyInt32 o) {\n    v = hn::Or(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  HwyInt32 operator<<(int n) const {\n    const HwyInt32Tag di;\n    return hn::Shl(v, hn::BitCast(di, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n))));\n  }\n  HwyInt32 operator>>(int n) const {\n    const HwyInt32Tag di;\n    return hn::Shr(v, hn::BitCast(di, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n))));\n  }\n  HwyInt32& operator<<=(int n) {\n    const HwyInt32Tag di;\n    v = hn::Shl(v, hn::BitCast(di, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n))));\n    return *this;\n  }\n  HwyInt32& operator>>=(int n) {\n    const HwyInt32Tag di;\n    v = hn::Shr(v, hn::BitCast(di, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n))));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend HwyInt32 operator+(HwyInt32 a, HwyInt32 b) {\n    return hn::Add(a.v, b.v);\n  }\n  friend HwyInt32 operator-(HwyInt32 a, HwyInt32 b) {\n    return hn::Sub(a.v, b.v);\n  }\n  friend HwyInt32 operator*(HwyInt32 a, HwyInt32 b) {\n    return hn::Mul(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend HwyInt32 operator&(HwyInt32 a, HwyInt32 b) {\n    return hn::And(a.v, b.v);\n  }\n  friend HwyInt32 operator|(HwyInt32 a, HwyInt32 b) {\n    return hn::Or(a.v, b.v);\n  }\n  friend HwyInt32 operator^(HwyInt32 a, HwyInt32 b) {\n    return hn::Xor(a.v, b.v);\n  }\n\n  friend HwyInt32 operator~(HwyInt32 a) {\n    return hn::Not(a.v);\n  }\n\n  // Comparisons return HwyInt32 masks (via VecFromMask).\n  friend HwyInt32 operator==(HwyInt32 a, HwyInt32 b) {\n    const HwyInt32Tag di;\n    return hn::VecFromMask(di, hn::Eq(a.v, b.v));\n  }\n  friend HwyInt32 operator!=(HwyInt32 a, HwyInt32 b) {\n    const HwyInt32Tag di;\n    return hn::VecFromMask(di, hn::Not(hn::Eq(a.v, b.v)));\n  }\n  friend HwyInt32 operator<(HwyInt32 a, HwyInt32 b) {\n    const HwyInt32Tag di;\n    return hn::VecFromMask(di, hn::Lt(a.v, b.v));\n  }\n  friend HwyInt32 operator>(HwyInt32 a, HwyInt32 b) {\n    const HwyInt32Tag di;\n    return hn::VecFromMask(di, hn::Gt(a.v, b.v));\n  }\n\n  friend HwyInt32 operator!(HwyInt32 a) {\n    const HwyInt32Tag di;\n    return hn::VecFromMask(di, hn::Eq(a.v, hn::Zero(di)));\n  }\n};\n\n// N-wide uint32 SIMD wrapper around Highway Vec<RebindToUnsigned<ScalableTag<float>>>.\nstruct HwyUint32 {\n  hn::Vec<HwyUint32Tag> v;\n\n  HwyUint32() = default;\n  HwyUint32(hn::Vec<HwyUint32Tag> vec) : v(vec) {}\n  HwyUint32(uint32_t u) : v(hn::Set(HwyUint32Tag{}, u)) {}\n  // Reinterpret from HwyInt32 (no-op).\n  HwyUint32(HwyInt32 i) : v(hn::BitCast(HwyUint32Tag{}, i.v)) {}\n\n  HwyUint32& operator+=(HwyUint32 o) {\n    v = hn::Add(v, o.v);\n    return *this;\n  }\n  HwyUint32& operator-=(HwyUint32 o) {\n    v = hn::Sub(v, o.v);\n    return *this;\n  }\n  HwyUint32& operator*=(HwyUint32 o) {\n    v = hn::Mul(v, o.v);\n    return *this;\n  }\n  HwyUint32& operator&=(HwyUint32 o) {\n    v = hn::And(v, o.v);\n    return *this;\n  }\n  HwyUint32& operator|=(HwyUint32 o) {\n    v = hn::Or(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  HwyUint32 operator<<(int n) const {\n    return hn::Shl(v, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n)));\n  }\n  HwyUint32 operator>>(int n) const {\n    return hn::Shr(v, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n)));\n  }\n  HwyUint32& operator<<=(int n) {\n    v = hn::Shl(v, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n)));\n    return *this;\n  }\n  HwyUint32& operator>>=(int n) {\n    v = hn::Shr(v, hn::Set(HwyUint32Tag{}, static_cast<uint32_t>(n)));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend HwyUint32 operator+(HwyUint32 a, HwyUint32 b) {\n    return hn::Add(a.v, b.v);\n  }\n  friend HwyUint32 operator-(HwyUint32 a, HwyUint32 b) {\n    return hn::Sub(a.v, b.v);\n  }\n  friend HwyUint32 operator*(HwyUint32 a, HwyUint32 b) {\n    return hn::Mul(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend HwyUint32 operator&(HwyUint32 a, HwyUint32 b) {\n    return hn::And(a.v, b.v);\n  }\n  friend HwyUint32 operator|(HwyUint32 a, HwyUint32 b) {\n    return hn::Or(a.v, b.v);\n  }\n  friend HwyUint32 operator^(HwyUint32 a, HwyUint32 b) {\n    return hn::Xor(a.v, b.v);\n  }\n\n  friend HwyUint32 operator~(HwyUint32 a) {\n    return hn::Not(a.v);\n  }\n\n  // Comparisons.\n  friend HwyUint32 operator==(HwyUint32 a, HwyUint32 b) {\n    const HwyUint32Tag du;\n    return hn::VecFromMask(du, hn::Eq(a.v, b.v));\n  }\n  friend HwyUint32 operator!=(HwyUint32 a, HwyUint32 b) {\n    const HwyUint32Tag du;\n    return hn::VecFromMask(du, hn::Not(hn::Eq(a.v, b.v)));\n  }\n  friend HwyUint32 operator>(HwyUint32 a, HwyUint32 b) {\n    const HwyUint32Tag du;\n    return hn::VecFromMask(du, hn::Gt(a.v, b.v));\n  }\n  friend HwyUint32 operator<(HwyUint32 a, HwyUint32 b) {\n    const HwyUint32Tag du;\n    return hn::VecFromMask(du, hn::Lt(a.v, b.v));\n  }\n\n  friend HwyUint32 operator!(HwyUint32 a) {\n    const HwyUint32Tag du;\n    return hn::VecFromMask(du, hn::Eq(a.v, hn::Zero(du)));\n  }\n};\n\n// --- Deferred inline definitions ---\n\n// HwyFloat ↔ HwyInt32 conversion.\ninline HwyFloat::HwyFloat(HwyInt32 i) : v(hn::ConvertTo(HwyFloatTag{}, i.v)) {}\n\n// HwyInt32 ↔ HwyUint32 reinterpret (no-op).\ninline HwyInt32::HwyInt32(HwyUint32 u) : v(hn::BitCast(HwyInt32Tag{}, u.v)) {}\n\n// Map raw Highway vector to HwyFloat for SimdTypeFor.\ntemplate <>\nstruct SimdTypeFor<hn::Vec<HwyFloatTag>> {\n  using type = HwyFloat;\n};\n\n// --- bit_cast specializations ---\n\ntemplate <>\ninline HwyInt32 bit_cast<HwyInt32>(const HwyFloat& f) noexcept {\n  return hn::BitCast(HwyInt32Tag{}, f.v);\n}\ntemplate <>\ninline HwyUint32 bit_cast<HwyUint32>(const HwyFloat& f) noexcept {\n  return hn::BitCast(HwyUint32Tag{}, f.v);\n}\ntemplate <>\ninline HwyFloat bit_cast<HwyFloat>(const HwyInt32& i) noexcept {\n  return hn::BitCast(HwyFloatTag{}, i.v);\n}\ntemplate <>\ninline HwyFloat bit_cast<HwyFloat>(const HwyUint32& u) noexcept {\n  return hn::BitCast(HwyFloatTag{}, u.v);\n}\ntemplate <>\ninline HwyInt32 bit_cast<HwyInt32>(const HwyUint32& u) noexcept {\n  return hn::BitCast(HwyInt32Tag{}, u.v);\n}\ntemplate <>\ninline HwyUint32 bit_cast<HwyUint32>(const HwyInt32& i) noexcept {\n  return hn::BitCast(HwyUint32Tag{}, i.v);\n}\n\n// --- FloatTraits<HwyFloat> ---\n\ntemplate <>\nstruct FloatTraits<HwyFloat> {\n  using IntType = HwyInt32;\n  using UintType = HwyUint32;\n  using BoolType = HwyFloat; // Float comparison masks (lane-wide)\n\n  static constexpr uint32_t kOne = 0x3f800000;\n  static constexpr float kMagic = 12582912.f;\n  static constexpr bool kBoolIsMask = true;\n\n  static DISPENSO_INLINE HwyFloat sqrt(HwyFloat x) {\n    return hn::Sqrt(x.v);\n  }\n\n  static DISPENSO_INLINE HwyFloat rcp(HwyFloat x) {\n    return hn::ApproximateReciprocal(x.v);\n  }\n\n  // Highway always has FMA.\n  static DISPENSO_INLINE HwyFloat fma(HwyFloat a, HwyFloat b, HwyFloat c) {\n    return hn::MulAdd(a.v, b.v, c.v);\n  }\n\n  // conditional: select x where mask is true, y where false.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(HwyFloat mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(HwyInt32 mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(HwyFloat mask, Arg x);\n\n  static DISPENSO_INLINE HwyFloat min(HwyFloat a, HwyFloat b) {\n    return hn::Min(a.v, b.v);\n  }\n\n  static DISPENSO_INLINE HwyFloat max(HwyFloat a, HwyFloat b) {\n    return hn::Max(a.v, b.v);\n  }\n};\n\n// conditional specializations (HwyFloat mask).\n// MaskFromVec extracts MSB: all-ones → true, all-zeros → false.\ntemplate <>\ninline HwyFloat FloatTraits<HwyFloat>::conditional(HwyFloat mask, HwyFloat x, HwyFloat y) {\n  auto m = hn::MaskFromVec(mask.v);\n  return hn::IfThenElse(m, x.v, y.v);\n}\ntemplate <>\ninline HwyInt32 FloatTraits<HwyFloat>::conditional(HwyFloat mask, HwyInt32 x, HwyInt32 y) {\n  const HwyInt32Tag di;\n  auto imask = hn::BitCast(di, mask.v);\n  auto m = hn::MaskFromVec(imask);\n  return hn::IfThenElse(m, x.v, y.v);\n}\ntemplate <>\ninline HwyUint32 FloatTraits<HwyFloat>::conditional(HwyFloat mask, HwyUint32 x, HwyUint32 y) {\n  const HwyUint32Tag du;\n  auto umask = hn::BitCast(du, mask.v);\n  auto m = hn::MaskFromVec(umask);\n  return hn::IfThenElse(m, x.v, y.v);\n}\n\n// conditional specializations (HwyInt32 lane-wide mask).\ntemplate <>\ninline HwyFloat FloatTraits<HwyFloat>::conditional(HwyInt32 mask, HwyFloat x, HwyFloat y) {\n  const HwyFloatTag d;\n  auto fmask = hn::BitCast(d, mask.v);\n  auto m = hn::MaskFromVec(fmask);\n  return hn::IfThenElse(m, x.v, y.v);\n}\ntemplate <>\ninline HwyInt32 FloatTraits<HwyFloat>::conditional(HwyInt32 mask, HwyInt32 x, HwyInt32 y) {\n  auto m = hn::MaskFromVec(mask.v);\n  return hn::IfThenElse(m, x.v, y.v);\n}\ntemplate <>\ninline HwyUint32 FloatTraits<HwyFloat>::conditional(HwyInt32 mask, HwyUint32 x, HwyUint32 y) {\n  const HwyUint32Tag du;\n  auto umask = hn::BitCast(du, mask.v);\n  auto m = hn::MaskFromVec(umask);\n  return hn::IfThenElse(m, x.v, y.v);\n}\n\n// apply: mask & x (bitwise AND).\ntemplate <>\ninline HwyFloat FloatTraits<HwyFloat>::apply(HwyFloat mask, HwyFloat x) {\n  const HwyFloatTag d;\n  const HwyInt32Tag di;\n  return hn::BitCast(d, hn::And(hn::BitCast(di, mask.v), hn::BitCast(di, x.v)));\n}\ntemplate <>\ninline HwyInt32 FloatTraits<HwyFloat>::apply(HwyFloat mask, HwyInt32 x) {\n  const HwyInt32Tag di;\n  return hn::And(hn::BitCast(di, mask.v), x.v);\n}\ntemplate <>\ninline HwyUint32 FloatTraits<HwyFloat>::apply(HwyFloat mask, HwyUint32 x) {\n  const HwyUint32Tag du;\n  return hn::And(hn::BitCast(du, mask.v), x.v);\n}\n\ntemplate <>\nstruct FloatTraits<HwyInt32> {\n  using IntType = HwyInt32;\n};\n\ntemplate <>\nstruct FloatTraits<HwyUint32> {\n  using IntType = HwyUint32;\n};\n\n// --- Util function overloads for Highway types ---\n\nDISPENSO_INLINE HwyFloat floor_small(HwyFloat x) {\n  return hn::Floor(x.v);\n}\n\nDISPENSO_INLINE HwyInt32 convert_to_int_trunc(HwyFloat f) {\n  const HwyInt32Tag di;\n  // ConvertTo truncates toward zero (no Round needed).\n  return hn::ConvertTo(di, f.v);\n}\n\nDISPENSO_INLINE HwyInt32 convert_to_int_trunc_safe(HwyFloat f) {\n  const HwyInt32Tag di;\n  auto converted = hn::ConvertTo(di, f.v);\n  HwyInt32 fi = bit_cast<HwyInt32>(f);\n  HwyInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & HwyInt32(converted);\n}\n\nDISPENSO_INLINE HwyInt32 convert_to_int(HwyFloat f) {\n  const HwyInt32Tag di;\n  // Round to nearest even, then convert to int.\n  auto rounded = hn::Round(f.v);\n  auto converted = hn::ConvertTo(di, rounded);\n  // Mask non-normals to 0 to avoid undefined behavior.\n  HwyInt32 fi = bit_cast<HwyInt32>(f);\n  HwyInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & HwyInt32(converted);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyFloat min<HwyFloat>(HwyFloat x, HwyFloat mn) {\n  // If x is NaN, return mn. Explicit NaN handling for portability.\n  auto is_num = hn::Eq(x.v, x.v); // true for non-NaN\n  auto result = hn::Min(x.v, mn.v);\n  return hn::IfThenElse(is_num, result, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyFloat clamp_allow_nan<HwyFloat>(HwyFloat x, HwyFloat mn, HwyFloat mx) {\n  // NaN propagates: if x is NaN, result is NaN.\n  auto is_nan = hn::Not(hn::Eq(x.v, x.v));\n  auto clamped = hn::Max(mn.v, hn::Min(mx.v, x.v));\n  return hn::IfThenElse(is_nan, x.v, clamped);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyFloat clamp_no_nan<HwyFloat>(HwyFloat x, HwyFloat mn, HwyFloat mx) {\n  // Highway's Min/Max follow IEEE 754-2019 minimum/maximum semantics: if\n  // either operand is NaN, the result is NaN. But we want NaN-suppressing\n  // behavior (like x86 minps/maxps): if x is NaN, result should be mn.\n  // Clamp(x) = Max(mn, Min(x, mx)). With NaN x:\n  //   Min(NaN, mx) = NaN → Max(mn, NaN) = NaN. Wrong — we want mn.\n  // Fix: use ordered comparison to detect NaN lanes and blend.\n  auto clamped = hn::Max(mn.v, hn::Min(x.v, mx.v));\n  auto x_valid = hn::Eq(x.v, x.v); // false for NaN lanes\n  return hn::IfThenElse(x_valid, clamped, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyFloat gather<HwyFloat>(const float* table, HwyInt32 index) {\n  const HwyFloatTag d;\n  return hn::GatherIndex(d, table, index.v);\n}\n\nDISPENSO_INLINE HwyInt32 int_div_by_3(HwyInt32 i) {\n  // Multiply each 32-bit lane by 0x55555556 and take the high 32 bits.\n  // Uses widening MulEven/MulOdd to stay in SIMD registers (no scalar fallback).\n  const HwyUint32Tag du;\n  const HwyInt32Tag di;\n  auto ui = hn::BitCast(du, i.v);\n  auto mul = hn::Set(du, 0x55555556u);\n  // Even lanes (0, 2, ...): widening 32×32→64 multiply.\n  auto even_prod = hn::MulEven(ui, mul);\n  // Odd lanes (1, 3, ...): widening 32×32→64 multiply.\n  auto odd_prod = hn::MulOdd(ui, mul);\n  // Extract high 32 bits of each 64-bit product.\n  auto even_hi = hn::ShiftRight<32>(even_prod);\n  auto odd_hi = hn::ShiftRight<32>(odd_prod);\n  // Interleave: odd results into upper 32 bits of each 64-bit lane, OR with even.\n  auto combined = hn::Or(even_hi, hn::ShiftLeft<32>(odd_hi));\n  return hn::BitCast(di, combined);\n}\n\n// nonnormal/nonnormalOrZero: return HwyInt32 masks.\nDISPENSO_INLINE HwyInt32 nonnormal(HwyInt32 i) {\n  return (i & 0x7f800000) == 0x7f800000;\n}\n\nDISPENSO_INLINE HwyInt32 nonnormalOrZero(HwyInt32 i) {\n  auto m = i & 0x7f800000;\n  return (m == 0x7f800000) | (m == 0);\n}\n\nDISPENSO_INLINE HwyInt32 nonnormal(HwyFloat f) {\n  return nonnormal(bit_cast<HwyInt32>(f));\n}\n\n// any_true: reduce SIMD mask to scalar bool (true if any lane is set).\nDISPENSO_INLINE bool any_true(HwyInt32 mask) {\n  hn::ScalableTag<int32_t> d;\n  return !hn::AllFalse(d, hn::Ne(mask.v, hn::Zero(d)));\n}\n\nDISPENSO_INLINE HwyFloat signof(HwyFloat x) {\n  HwyUint32 xi = bit_cast<HwyUint32>(x);\n  return bit_cast<HwyFloat>((xi & 0x80000000u) | FloatTraits<HwyFloat>::kOne);\n}\n\nDISPENSO_INLINE HwyInt32 signofi(HwyInt32 i) {\n  return HwyInt32(1) - (HwyInt32(2) & (i < HwyInt32(0)));\n}\n\n// nbool_as_one: 0 if mask is true (all-ones), 1 if false (all-zeros).\ntemplate <>\nDISPENSO_INLINE HwyFloat nbool_as_one<HwyFloat, HwyFloat>(HwyFloat b) {\n  const HwyFloatTag d;\n  const HwyInt32Tag di;\n  auto bi = hn::BitCast(di, b.v);\n  auto one_bits = hn::Set(di, 0x3f800000);\n  return hn::BitCast(d, hn::AndNot(bi, one_bits));\n}\n\ntemplate <>\nDISPENSO_INLINE HwyInt32 nbool_as_one<HwyInt32, HwyFloat>(HwyFloat b) {\n  const HwyInt32Tag di;\n  auto bi = hn::BitCast(di, b.v);\n  return hn::AndNot(bi, hn::Set(di, 1));\n}\n\ntemplate <>\nDISPENSO_INLINE HwyInt32 nbool_as_one<HwyInt32, HwyInt32>(HwyInt32 b) {\n  const HwyInt32Tag di;\n  return hn::AndNot(b.v, hn::Set(di, 1));\n}\n\n// bool_as_one: 1 if mask is true, 0 if false.\ntemplate <>\nDISPENSO_INLINE HwyFloat bool_as_one<HwyFloat, HwyFloat>(HwyFloat b) {\n  const HwyFloatTag d;\n  const HwyInt32Tag di;\n  auto bi = hn::BitCast(di, b.v);\n  return hn::BitCast(d, hn::And(bi, hn::Set(di, 0x3f800000)));\n}\n\ntemplate <>\nDISPENSO_INLINE HwyInt32 bool_as_one<HwyInt32, HwyFloat>(HwyFloat b) {\n  const HwyInt32Tag di;\n  auto bi = hn::BitCast(di, b.v);\n  return hn::And(bi, hn::Set(di, 1));\n}\n\n// bool_as_mask: for SIMD masks, identity (already a mask).\ntemplate <>\nDISPENSO_INLINE HwyInt32 bool_as_mask<HwyInt32, HwyFloat>(HwyFloat b) {\n  return hn::BitCast(HwyInt32Tag{}, b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyInt32 bool_as_mask<HwyInt32, HwyInt32>(HwyInt32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE HwyInt32 bool_as_mask<HwyInt32, HwyUint32>(HwyUint32 b) {\n  return hn::BitCast(HwyInt32Tag{}, b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyUint32 bool_as_mask<HwyUint32, HwyFloat>(HwyFloat b) {\n  return hn::BitCast(HwyUint32Tag{}, b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE HwyUint32 bool_as_mask<HwyUint32, HwyUint32>(HwyUint32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE HwyUint32 bool_as_mask<HwyUint32, HwyInt32>(HwyInt32 b) {\n  return hn::BitCast(HwyUint32Tag{}, b.v);\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n#endif // __has_include(\"hwy/highway.h\")\n"
  },
  {
    "path": "dispenso/fast_math/float_traits_neon.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#if defined(__aarch64__)\n\n#include <arm_neon.h>\n\n#include <cstdint>\n\n#include \"float_traits.h\"\n#include \"util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nstruct NeonInt32;\nstruct NeonUint32;\n\n// 4-wide float SIMD wrapper around float32x4_t (AArch64 NEON).\nstruct NeonFloat {\n  float32x4_t v;\n\n  NeonFloat() = default;\n  NeonFloat(float32x4_t vec) : v(vec) {}\n  // Implicit broadcast from scalar — required for polynomial constant propagation.\n  NeonFloat(float f) : v(vdupq_n_f32(f)) {}\n  // Explicit int→float conversion for (Flt)intExpr patterns.\n  explicit NeonFloat(NeonInt32 i);\n\n  NeonFloat operator-() const {\n    return vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(v), vdupq_n_u32(0x80000000)));\n  }\n\n  NeonFloat& operator+=(NeonFloat o) {\n    v = vaddq_f32(v, o.v);\n    return *this;\n  }\n  NeonFloat& operator-=(NeonFloat o) {\n    v = vsubq_f32(v, o.v);\n    return *this;\n  }\n  NeonFloat& operator*=(NeonFloat o) {\n    v = vmulq_f32(v, o.v);\n    return *this;\n  }\n  NeonFloat& operator&=(NeonFloat o) {\n    v = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(v), vreinterpretq_u32_f32(o.v)));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend NeonFloat operator+(NeonFloat a, NeonFloat b) {\n    return vaddq_f32(a.v, b.v);\n  }\n  friend NeonFloat operator-(NeonFloat a, NeonFloat b) {\n    return vsubq_f32(a.v, b.v);\n  }\n  friend NeonFloat operator*(NeonFloat a, NeonFloat b) {\n    return vmulq_f32(a.v, b.v);\n  }\n  friend NeonFloat operator/(NeonFloat a, NeonFloat b) {\n    return vdivq_f32(a.v, b.v);\n  }\n\n  // Comparisons return NeonFloat masks (all-ones or all-zeros per lane).\n  // NEON comparisons produce uint32x4_t; reinterpret to float32x4_t.\n  friend NeonFloat operator<(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vcltq_f32(a.v, b.v));\n  }\n  friend NeonFloat operator>(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vcgtq_f32(a.v, b.v));\n  }\n  friend NeonFloat operator<=(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vcleq_f32(a.v, b.v));\n  }\n  friend NeonFloat operator>=(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vcgeq_f32(a.v, b.v));\n  }\n  friend NeonFloat operator==(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vceqq_f32(a.v, b.v));\n  }\n  friend NeonFloat operator!=(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vmvnq_u32(vceqq_f32(a.v, b.v)));\n  }\n\n  // Logical NOT of a comparison mask.\n  friend NeonFloat operator!(NeonFloat a) {\n    return vreinterpretq_f32_u32(vmvnq_u32(vreinterpretq_u32_f32(a.v)));\n  }\n\n  // Bitwise ops on float masks.\n  friend NeonFloat operator&(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(a.v), vreinterpretq_u32_f32(b.v)));\n  }\n  friend NeonFloat operator|(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(a.v), vreinterpretq_u32_f32(b.v)));\n  }\n  friend NeonFloat operator^(NeonFloat a, NeonFloat b) {\n    return vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(a.v), vreinterpretq_u32_f32(b.v)));\n  }\n};\n\n// 4-wide int32 SIMD wrapper around int32x4_t.\nstruct NeonInt32 {\n  int32x4_t v;\n\n  NeonInt32() = default;\n  NeonInt32(int32x4_t vec) : v(vec) {}\n  NeonInt32(int32_t i) : v(vdupq_n_s32(i)) {}\n  // Reinterpret from NeonUint32 (no-op).\n  NeonInt32(NeonUint32 u);\n\n  NeonInt32 operator-() const {\n    return vnegq_s32(v);\n  }\n\n  NeonInt32& operator+=(NeonInt32 o) {\n    v = vaddq_s32(v, o.v);\n    return *this;\n  }\n  NeonInt32& operator-=(NeonInt32 o) {\n    v = vsubq_s32(v, o.v);\n    return *this;\n  }\n  NeonInt32& operator*=(NeonInt32 o) {\n    v = vmulq_s32(v, o.v);\n    return *this;\n  }\n  NeonInt32& operator&=(NeonInt32 o) {\n    v = vandq_s32(v, o.v);\n    return *this;\n  }\n  NeonInt32& operator|=(NeonInt32 o) {\n    v = vorrq_s32(v, o.v);\n    return *this;\n  }\n\n  // Shifts (NEON uses vshlq with signed shift amount: positive=left, negative=right).\n  NeonInt32 operator<<(int n) const {\n    return vshlq_s32(v, vdupq_n_s32(n));\n  }\n  NeonInt32 operator>>(int n) const {\n    return vshlq_s32(v, vdupq_n_s32(-n)); // Arithmetic right shift\n  }\n  NeonInt32& operator<<=(int n) {\n    v = vshlq_s32(v, vdupq_n_s32(n));\n    return *this;\n  }\n  NeonInt32& operator>>=(int n) {\n    v = vshlq_s32(v, vdupq_n_s32(-n));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend NeonInt32 operator+(NeonInt32 a, NeonInt32 b) {\n    return vaddq_s32(a.v, b.v);\n  }\n  friend NeonInt32 operator-(NeonInt32 a, NeonInt32 b) {\n    return vsubq_s32(a.v, b.v);\n  }\n  friend NeonInt32 operator*(NeonInt32 a, NeonInt32 b) {\n    return vmulq_s32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend NeonInt32 operator&(NeonInt32 a, NeonInt32 b) {\n    return vandq_s32(a.v, b.v);\n  }\n  friend NeonInt32 operator|(NeonInt32 a, NeonInt32 b) {\n    return vorrq_s32(a.v, b.v);\n  }\n  friend NeonInt32 operator^(NeonInt32 a, NeonInt32 b) {\n    return veorq_s32(a.v, b.v);\n  }\n\n  friend NeonInt32 operator~(NeonInt32 a) {\n    return vmvnq_s32(a.v);\n  }\n\n  // Comparisons return NeonInt32 masks (reinterpreted from uint32x4_t).\n  friend NeonInt32 operator==(NeonInt32 a, NeonInt32 b) {\n    return vreinterpretq_s32_u32(vceqq_s32(a.v, b.v));\n  }\n  friend NeonInt32 operator!=(NeonInt32 a, NeonInt32 b) {\n    return vreinterpretq_s32_u32(vmvnq_u32(vceqq_s32(a.v, b.v)));\n  }\n  friend NeonInt32 operator<(NeonInt32 a, NeonInt32 b) {\n    return vreinterpretq_s32_u32(vcltq_s32(a.v, b.v));\n  }\n  friend NeonInt32 operator>(NeonInt32 a, NeonInt32 b) {\n    return vreinterpretq_s32_u32(vcgtq_s32(a.v, b.v));\n  }\n\n  friend NeonInt32 operator!(NeonInt32 a) {\n    return vreinterpretq_s32_u32(vceqq_s32(a.v, vdupq_n_s32(0)));\n  }\n};\n\n// 4-wide uint32 SIMD wrapper around uint32x4_t.\nstruct NeonUint32 {\n  uint32x4_t v;\n\n  NeonUint32() = default;\n  NeonUint32(uint32x4_t vec) : v(vec) {}\n  NeonUint32(uint32_t u) : v(vdupq_n_u32(u)) {}\n  // Reinterpret from NeonInt32 (no-op).\n  NeonUint32(NeonInt32 i) : v(vreinterpretq_u32_s32(i.v)) {}\n\n  NeonUint32& operator+=(NeonUint32 o) {\n    v = vaddq_u32(v, o.v);\n    return *this;\n  }\n  NeonUint32& operator-=(NeonUint32 o) {\n    v = vsubq_u32(v, o.v);\n    return *this;\n  }\n  NeonUint32& operator*=(NeonUint32 o) {\n    v = vmulq_u32(v, o.v);\n    return *this;\n  }\n  NeonUint32& operator&=(NeonUint32 o) {\n    v = vandq_u32(v, o.v);\n    return *this;\n  }\n  NeonUint32& operator|=(NeonUint32 o) {\n    v = vorrq_u32(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  NeonUint32 operator<<(int n) const {\n    return vshlq_u32(v, vdupq_n_s32(n));\n  }\n  NeonUint32 operator>>(int n) const {\n    return vshlq_u32(v, vdupq_n_s32(-n)); // Logical right shift\n  }\n  NeonUint32& operator<<=(int n) {\n    v = vshlq_u32(v, vdupq_n_s32(n));\n    return *this;\n  }\n  NeonUint32& operator>>=(int n) {\n    v = vshlq_u32(v, vdupq_n_s32(-n));\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend NeonUint32 operator+(NeonUint32 a, NeonUint32 b) {\n    return vaddq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator-(NeonUint32 a, NeonUint32 b) {\n    return vsubq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator*(NeonUint32 a, NeonUint32 b) {\n    return vmulq_u32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend NeonUint32 operator&(NeonUint32 a, NeonUint32 b) {\n    return vandq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator|(NeonUint32 a, NeonUint32 b) {\n    return vorrq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator^(NeonUint32 a, NeonUint32 b) {\n    return veorq_u32(a.v, b.v);\n  }\n\n  friend NeonUint32 operator~(NeonUint32 a) {\n    return vmvnq_u32(a.v);\n  }\n\n  // NEON has native unsigned comparisons.\n  friend NeonUint32 operator==(NeonUint32 a, NeonUint32 b) {\n    return vceqq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator!=(NeonUint32 a, NeonUint32 b) {\n    return vmvnq_u32(vceqq_u32(a.v, b.v));\n  }\n  friend NeonUint32 operator>(NeonUint32 a, NeonUint32 b) {\n    return vcgtq_u32(a.v, b.v);\n  }\n  friend NeonUint32 operator<(NeonUint32 a, NeonUint32 b) {\n    return vcltq_u32(a.v, b.v);\n  }\n\n  friend NeonUint32 operator!(NeonUint32 a) {\n    return vceqq_u32(a.v, vdupq_n_u32(0));\n  }\n};\n\n// --- Deferred inline definitions ---\n\n// NeonFloat ↔ NeonInt32 conversion.\ninline NeonFloat::NeonFloat(NeonInt32 i) : v(vcvtq_f32_s32(i.v)) {}\n\n// NeonInt32 ↔ NeonUint32 reinterpret (no-op).\ninline NeonInt32::NeonInt32(NeonUint32 u) : v(vreinterpretq_s32_u32(u.v)) {}\n\n// Map raw float32x4_t to NeonFloat for SimdTypeFor.\ntemplate <>\nstruct SimdTypeFor<float32x4_t> {\n  using type = NeonFloat;\n};\n\n// --- bit_cast specializations ---\n\ntemplate <>\ninline NeonInt32 bit_cast<NeonInt32>(const NeonFloat& f) noexcept {\n  return vreinterpretq_s32_f32(f.v);\n}\ntemplate <>\ninline NeonUint32 bit_cast<NeonUint32>(const NeonFloat& f) noexcept {\n  return vreinterpretq_u32_f32(f.v);\n}\ntemplate <>\ninline NeonFloat bit_cast<NeonFloat>(const NeonInt32& i) noexcept {\n  return vreinterpretq_f32_s32(i.v);\n}\ntemplate <>\ninline NeonFloat bit_cast<NeonFloat>(const NeonUint32& u) noexcept {\n  return vreinterpretq_f32_u32(u.v);\n}\ntemplate <>\ninline NeonInt32 bit_cast<NeonInt32>(const NeonUint32& u) noexcept {\n  return vreinterpretq_s32_u32(u.v);\n}\ntemplate <>\ninline NeonUint32 bit_cast<NeonUint32>(const NeonInt32& i) noexcept {\n  return vreinterpretq_u32_s32(i.v);\n}\n\n// --- FloatTraits<NeonFloat> ---\n\ntemplate <>\nstruct FloatTraits<NeonFloat> {\n  using IntType = NeonInt32;\n  using UintType = NeonUint32;\n  using BoolType = NeonFloat; // Float comparison masks (lane-wide, like SSE)\n\n  static constexpr uint32_t kOne = 0x3f800000;\n  static constexpr float kMagic = 12582912.f;\n  static constexpr bool kBoolIsMask = true;\n\n  static DISPENSO_INLINE NeonFloat sqrt(NeonFloat x) {\n    return vsqrtq_f32(x.v);\n  }\n\n  static DISPENSO_INLINE NeonFloat rcp(NeonFloat x) {\n    return vrecpeq_f32(x.v);\n  }\n\n  // AArch64 always has FMA.\n  static DISPENSO_INLINE NeonFloat fma(NeonFloat a, NeonFloat b, NeonFloat c) {\n    return vfmaq_f32(c.v, a.v, b.v); // vfmaq_f32(acc, a, b) = acc + a*b\n  }\n\n  // conditional: select x where mask is true, y where false.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(NeonFloat mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(NeonInt32 mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(NeonFloat mask, Arg x);\n\n  static DISPENSO_INLINE NeonFloat min(NeonFloat a, NeonFloat b) {\n    return vminnmq_f32(a.v, b.v);\n  }\n\n  static DISPENSO_INLINE NeonFloat max(NeonFloat a, NeonFloat b) {\n    return vmaxnmq_f32(a.v, b.v);\n  }\n};\n\n// conditional specializations (NeonFloat mask).\n// vbslq selects from first operand where mask bits are 1, second where 0.\ntemplate <>\ninline NeonFloat FloatTraits<NeonFloat>::conditional(NeonFloat mask, NeonFloat x, NeonFloat y) {\n  return vbslq_f32(vreinterpretq_u32_f32(mask.v), x.v, y.v);\n}\ntemplate <>\ninline NeonInt32 FloatTraits<NeonFloat>::conditional(NeonFloat mask, NeonInt32 x, NeonInt32 y) {\n  return vreinterpretq_s32_u32(vbslq_u32(\n      vreinterpretq_u32_f32(mask.v), vreinterpretq_u32_s32(x.v), vreinterpretq_u32_s32(y.v)));\n}\ntemplate <>\ninline NeonUint32 FloatTraits<NeonFloat>::conditional(NeonFloat mask, NeonUint32 x, NeonUint32 y) {\n  return vbslq_u32(vreinterpretq_u32_f32(mask.v), x.v, y.v);\n}\n\n// conditional specializations (NeonInt32 lane-wide mask).\ntemplate <>\ninline NeonFloat FloatTraits<NeonFloat>::conditional(NeonInt32 mask, NeonFloat x, NeonFloat y) {\n  return vbslq_f32(vreinterpretq_u32_s32(mask.v), x.v, y.v);\n}\ntemplate <>\ninline NeonInt32 FloatTraits<NeonFloat>::conditional(NeonInt32 mask, NeonInt32 x, NeonInt32 y) {\n  return vreinterpretq_s32_u32(vbslq_u32(\n      vreinterpretq_u32_s32(mask.v), vreinterpretq_u32_s32(x.v), vreinterpretq_u32_s32(y.v)));\n}\ntemplate <>\ninline NeonUint32 FloatTraits<NeonFloat>::conditional(NeonInt32 mask, NeonUint32 x, NeonUint32 y) {\n  return vbslq_u32(vreinterpretq_u32_s32(mask.v), x.v, y.v);\n}\n\n// apply: mask & x (bitwise AND).\ntemplate <>\ninline NeonFloat FloatTraits<NeonFloat>::apply(NeonFloat mask, NeonFloat x) {\n  return vreinterpretq_f32_u32(\n      vandq_u32(vreinterpretq_u32_f32(mask.v), vreinterpretq_u32_f32(x.v)));\n}\ntemplate <>\ninline NeonInt32 FloatTraits<NeonFloat>::apply(NeonFloat mask, NeonInt32 x) {\n  return vreinterpretq_s32_u32(\n      vandq_u32(vreinterpretq_u32_f32(mask.v), vreinterpretq_u32_s32(x.v)));\n}\ntemplate <>\ninline NeonUint32 FloatTraits<NeonFloat>::apply(NeonFloat mask, NeonUint32 x) {\n  return vandq_u32(vreinterpretq_u32_f32(mask.v), x.v);\n}\n\ntemplate <>\nstruct FloatTraits<NeonInt32> {\n  using IntType = NeonInt32;\n};\n\ntemplate <>\nstruct FloatTraits<NeonUint32> {\n  using IntType = NeonUint32;\n};\n\n// --- Util function overloads for NEON types ---\n\nDISPENSO_INLINE NeonFloat floor_small(NeonFloat x) {\n  return vrndmq_f32(x.v);\n}\n\nDISPENSO_INLINE NeonInt32 convert_to_int_trunc(NeonFloat f) {\n  return vcvtq_s32_f32(f.v);\n}\n\nDISPENSO_INLINE NeonInt32 convert_to_int_trunc_safe(NeonFloat f) {\n  NeonInt32 fi = bit_cast<NeonInt32>(f);\n  NeonInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & NeonInt32(vcvtq_s32_f32(f.v));\n}\n\nDISPENSO_INLINE NeonInt32 convert_to_int(NeonFloat f) {\n  // vcvtnq_s32_f32 uses round-to-nearest-even.\n  // Mask non-normals to 0 to avoid undefined behavior.\n  NeonInt32 fi = bit_cast<NeonInt32>(f);\n  NeonInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & NeonInt32(vcvtnq_s32_f32(f.v));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonFloat min<NeonFloat>(NeonFloat x, NeonFloat mn) {\n  // vminnmq_f32: if x is NaN, returns mn (the number). NaN-suppressing.\n  return vminnmq_f32(x.v, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE NeonFloat clamp_allow_nan<NeonFloat>(NeonFloat x, NeonFloat mn, NeonFloat mx) {\n  // Use NaN-propagating min/max (FMIN/FMAX) so NaN passes through.\n  return vmaxq_f32(mn.v, vminq_f32(mx.v, x.v));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonFloat clamp_no_nan<NeonFloat>(NeonFloat x, NeonFloat mn, NeonFloat mx) {\n  // Use NaN-suppressing min/max (FMINNM/FMAXNM) so NaN is replaced.\n  return vmaxnmq_f32(mn.v, vminnmq_f32(x.v, mx.v));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonFloat gather<NeonFloat>(const float* table, NeonInt32 index) {\n  // No NEON gather instruction; extract indices and load scalar.\n  alignas(16) int32_t idx[4];\n  vst1q_s32(idx, index.v);\n  float vals[4] = {table[idx[0]], table[idx[1]], table[idx[2]], table[idx[3]]};\n  return vld1q_f32(vals);\n}\n\nDISPENSO_INLINE NeonInt32 int_div_by_3(NeonInt32 i) {\n  // Multiply each lane by 0x55555556 and take the high 32 bits.\n  // Process low (lanes 0,1) and high (lanes 2,3) halves separately.\n  uint32x4_t ui = vreinterpretq_u32_s32(i.v);\n  uint32x2_t mul = vdup_n_u32(0x55555556);\n  // Low lanes (0, 1).\n  uint64x2_t lo_prod = vmull_u32(vget_low_u32(ui), mul);\n  uint32x2_t lo_result = vshrn_n_u64(lo_prod, 32);\n  // High lanes (2, 3).\n  uint64x2_t hi_prod = vmull_u32(vget_high_u32(ui), mul);\n  uint32x2_t hi_result = vshrn_n_u64(hi_prod, 32);\n  return vreinterpretq_s32_u32(vcombine_u32(lo_result, hi_result));\n}\n\n// nonnormal/nonnormalOrZero: return NeonInt32 masks for NEON types.\nDISPENSO_INLINE NeonInt32 nonnormal(NeonInt32 i) {\n  return (i & 0x7f800000) == 0x7f800000;\n}\n\nDISPENSO_INLINE NeonInt32 nonnormalOrZero(NeonInt32 i) {\n  auto m = i & 0x7f800000;\n  return (m == 0x7f800000) | (m == 0);\n}\n\nDISPENSO_INLINE NeonInt32 nonnormal(NeonFloat f) {\n  return nonnormal(bit_cast<NeonInt32>(f));\n}\n\n// any_true: reduce SIMD mask to scalar bool (true if any lane is set).\nDISPENSO_INLINE bool any_true(NeonInt32 mask) {\n  return vmaxvq_u32(vreinterpretq_u32_s32(mask.v)) != 0;\n}\n\nDISPENSO_INLINE NeonFloat signof(NeonFloat x) {\n  NeonUint32 xi = bit_cast<NeonUint32>(x);\n  return bit_cast<NeonFloat>((xi & 0x80000000u) | FloatTraits<NeonFloat>::kOne);\n}\n\nDISPENSO_INLINE NeonInt32 signofi(NeonInt32 i) {\n  return NeonInt32(1) - (NeonInt32(2) & (i < NeonInt32(0)));\n}\n\n// nbool_as_one: 0 if mask is true (all-ones), 1 if false (all-zeros).\ntemplate <>\nDISPENSO_INLINE NeonFloat nbool_as_one<NeonFloat, NeonFloat>(NeonFloat b) {\n  // ~mask & 1.0f bits\n  return bit_cast<NeonFloat>(NeonInt32(\n      vreinterpretq_s32_u32(vbicq_u32(vdupq_n_u32(0x3f800000), vreinterpretq_u32_f32(b.v)))));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonInt32 nbool_as_one<NeonInt32, NeonFloat>(NeonFloat b) {\n  return vreinterpretq_s32_u32(vbicq_u32(vdupq_n_u32(1), vreinterpretq_u32_f32(b.v)));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonInt32 nbool_as_one<NeonInt32, NeonInt32>(NeonInt32 b) {\n  return vreinterpretq_s32_u32(vbicq_u32(vdupq_n_u32(1), vreinterpretq_u32_s32(b.v)));\n}\n\n// bool_as_one: 1 if mask is true, 0 if false.\ntemplate <>\nDISPENSO_INLINE NeonFloat bool_as_one<NeonFloat, NeonFloat>(NeonFloat b) {\n  return bit_cast<NeonFloat>(NeonInt32(\n      vreinterpretq_s32_u32(vandq_u32(vreinterpretq_u32_f32(b.v), vdupq_n_u32(0x3f800000)))));\n}\n\ntemplate <>\nDISPENSO_INLINE NeonInt32 bool_as_one<NeonInt32, NeonFloat>(NeonFloat b) {\n  return vreinterpretq_s32_u32(vandq_u32(vreinterpretq_u32_f32(b.v), vdupq_n_u32(1)));\n}\n\n// bool_as_mask: for SIMD masks, identity (already a mask).\ntemplate <>\nDISPENSO_INLINE NeonInt32 bool_as_mask<NeonInt32, NeonFloat>(NeonFloat b) {\n  return vreinterpretq_s32_f32(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE NeonInt32 bool_as_mask<NeonInt32, NeonInt32>(NeonInt32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE NeonInt32 bool_as_mask<NeonInt32, NeonUint32>(NeonUint32 b) {\n  return vreinterpretq_s32_u32(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE NeonUint32 bool_as_mask<NeonUint32, NeonFloat>(NeonFloat b) {\n  return vreinterpretq_u32_f32(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE NeonUint32 bool_as_mask<NeonUint32, NeonUint32>(NeonUint32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE NeonUint32 bool_as_mask<NeonUint32, NeonInt32>(NeonInt32 b) {\n  return vreinterpretq_u32_s32(b.v);\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n#endif // defined(__aarch64__)\n"
  },
  {
    "path": "dispenso/fast_math/float_traits_x86.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#if defined(__SSE4_1__)\n\n#include <immintrin.h>\n\n#include <cstdint>\n\n#include \"float_traits.h\"\n#include \"util.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\nstruct SseInt32;\nstruct SseUint32;\n\n// 4-wide float SIMD wrapper around __m128.\nstruct SseFloat {\n  __m128 v;\n\n  SseFloat() = default;\n  SseFloat(__m128 vec) : v(vec) {}\n  // Implicit broadcast from scalar — required for polynomial constant propagation.\n  SseFloat(float f) : v(_mm_set1_ps(f)) {}\n  // Explicit int→float conversion for (Flt)intExpr patterns.\n  explicit SseFloat(SseInt32 i);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m128() const {\n    return v;\n  }\n\n  SseFloat operator-() const {\n    return _mm_xor_ps(v, _mm_set1_ps(-0.0f));\n  }\n\n  SseFloat& operator+=(SseFloat o) {\n    v = _mm_add_ps(v, o.v);\n    return *this;\n  }\n  SseFloat& operator-=(SseFloat o) {\n    v = _mm_sub_ps(v, o.v);\n    return *this;\n  }\n  SseFloat& operator*=(SseFloat o) {\n    v = _mm_mul_ps(v, o.v);\n    return *this;\n  }\n  SseFloat& operator&=(SseFloat o) {\n    v = _mm_and_ps(v, o.v);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend SseFloat operator+(SseFloat a, SseFloat b) {\n    return _mm_add_ps(a.v, b.v);\n  }\n  friend SseFloat operator-(SseFloat a, SseFloat b) {\n    return _mm_sub_ps(a.v, b.v);\n  }\n  friend SseFloat operator*(SseFloat a, SseFloat b) {\n    return _mm_mul_ps(a.v, b.v);\n  }\n  friend SseFloat operator/(SseFloat a, SseFloat b) {\n    return _mm_div_ps(a.v, b.v);\n  }\n\n  // Comparisons return SseFloat masks (all-ones or all-zeros per lane).\n  friend SseFloat operator<(SseFloat a, SseFloat b) {\n    return _mm_cmplt_ps(a.v, b.v);\n  }\n  friend SseFloat operator>(SseFloat a, SseFloat b) {\n    return _mm_cmpgt_ps(a.v, b.v);\n  }\n  friend SseFloat operator<=(SseFloat a, SseFloat b) {\n    return _mm_cmple_ps(a.v, b.v);\n  }\n  friend SseFloat operator>=(SseFloat a, SseFloat b) {\n    return _mm_cmpge_ps(a.v, b.v);\n  }\n  friend SseFloat operator==(SseFloat a, SseFloat b) {\n    return _mm_cmpeq_ps(a.v, b.v);\n  }\n  friend SseFloat operator!=(SseFloat a, SseFloat b) {\n    return _mm_cmpneq_ps(a.v, b.v);\n  }\n\n  // Logical NOT of a comparison mask.\n  friend SseFloat operator!(SseFloat a) {\n    return _mm_xor_ps(a.v, _mm_castsi128_ps(_mm_set1_epi32(-1)));\n  }\n\n  // Bitwise ops on float masks.\n  friend SseFloat operator&(SseFloat a, SseFloat b) {\n    return _mm_and_ps(a.v, b.v);\n  }\n  friend SseFloat operator|(SseFloat a, SseFloat b) {\n    return _mm_or_ps(a.v, b.v);\n  }\n  friend SseFloat operator^(SseFloat a, SseFloat b) {\n    return _mm_xor_ps(a.v, b.v);\n  }\n};\n\n// 4-wide int32 SIMD wrapper around __m128i.\nstruct SseInt32 {\n  __m128i v;\n\n  SseInt32() = default;\n  SseInt32(__m128i vec) : v(vec) {}\n  SseInt32(int32_t i) : v(_mm_set1_epi32(i)) {}\n  // Reinterpret from SseUint32 (no-op on __m128i).\n  SseInt32(SseUint32 u);\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m128i() const {\n    return v;\n  }\n\n  SseInt32 operator-() const {\n    return _mm_sub_epi32(_mm_setzero_si128(), v);\n  }\n\n  SseInt32& operator+=(SseInt32 o) {\n    v = _mm_add_epi32(v, o.v);\n    return *this;\n  }\n  SseInt32& operator-=(SseInt32 o) {\n    v = _mm_sub_epi32(v, o.v);\n    return *this;\n  }\n  SseInt32& operator*=(SseInt32 o) {\n    v = _mm_mullo_epi32(v, o.v);\n    return *this;\n  }\n  SseInt32& operator&=(SseInt32 o) {\n    v = _mm_and_si128(v, o.v);\n    return *this;\n  }\n  SseInt32& operator|=(SseInt32 o) {\n    v = _mm_or_si128(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  SseInt32 operator<<(int n) const {\n    return _mm_slli_epi32(v, n);\n  }\n  SseInt32 operator>>(int n) const {\n    return _mm_srai_epi32(v, n); // Arithmetic shift right\n  }\n  SseInt32& operator<<=(int n) {\n    v = _mm_slli_epi32(v, n);\n    return *this;\n  }\n  SseInt32& operator>>=(int n) {\n    v = _mm_srai_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend SseInt32 operator+(SseInt32 a, SseInt32 b) {\n    return _mm_add_epi32(a.v, b.v);\n  }\n  friend SseInt32 operator-(SseInt32 a, SseInt32 b) {\n    return _mm_sub_epi32(a.v, b.v);\n  }\n  friend SseInt32 operator*(SseInt32 a, SseInt32 b) {\n    return _mm_mullo_epi32(a.v, b.v); // SSE4.1\n  }\n\n  // Bitwise.\n  friend SseInt32 operator&(SseInt32 a, SseInt32 b) {\n    return _mm_and_si128(a.v, b.v);\n  }\n  friend SseInt32 operator|(SseInt32 a, SseInt32 b) {\n    return _mm_or_si128(a.v, b.v);\n  }\n  friend SseInt32 operator^(SseInt32 a, SseInt32 b) {\n    return _mm_xor_si128(a.v, b.v);\n  }\n\n  friend SseInt32 operator~(SseInt32 a) {\n    return _mm_xor_si128(a.v, _mm_set1_epi32(-1));\n  }\n\n  // Comparisons return SseInt32 masks.\n  friend SseInt32 operator==(SseInt32 a, SseInt32 b) {\n    return _mm_cmpeq_epi32(a.v, b.v);\n  }\n  friend SseInt32 operator!=(SseInt32 a, SseInt32 b) {\n    return _mm_xor_si128(_mm_cmpeq_epi32(a.v, b.v), _mm_set1_epi32(-1));\n  }\n  friend SseInt32 operator<(SseInt32 a, SseInt32 b) {\n    return _mm_cmplt_epi32(a.v, b.v);\n  }\n  friend SseInt32 operator>(SseInt32 a, SseInt32 b) {\n    return _mm_cmpgt_epi32(a.v, b.v);\n  }\n\n  friend SseInt32 operator!(SseInt32 a) {\n    return _mm_cmpeq_epi32(a.v, _mm_setzero_si128());\n  }\n};\n\n// 4-wide uint32 SIMD wrapper around __m128i.\nstruct SseUint32 {\n  __m128i v;\n\n  SseUint32() = default;\n  SseUint32(__m128i vec) : v(vec) {}\n  SseUint32(uint32_t u) : v(_mm_set1_epi32(static_cast<int32_t>(u))) {}\n  // Reinterpret from SseInt32 (no-op on __m128i).\n  SseUint32(SseInt32 i) : v(i.v) {}\n\n  // Implicit conversion back to raw intrinsic type.\n  operator __m128i() const {\n    return v;\n  }\n\n  SseUint32& operator+=(SseUint32 o) {\n    v = _mm_add_epi32(v, o.v);\n    return *this;\n  }\n  SseUint32& operator-=(SseUint32 o) {\n    v = _mm_sub_epi32(v, o.v);\n    return *this;\n  }\n  SseUint32& operator*=(SseUint32 o) {\n    v = _mm_mullo_epi32(v, o.v);\n    return *this;\n  }\n  SseUint32& operator&=(SseUint32 o) {\n    v = _mm_and_si128(v, o.v);\n    return *this;\n  }\n  SseUint32& operator|=(SseUint32 o) {\n    v = _mm_or_si128(v, o.v);\n    return *this;\n  }\n\n  // Shifts.\n  SseUint32 operator<<(int n) const {\n    return _mm_slli_epi32(v, n);\n  }\n  SseUint32 operator>>(int n) const {\n    return _mm_srli_epi32(v, n); // Logical shift right\n  }\n  SseUint32& operator<<=(int n) {\n    v = _mm_slli_epi32(v, n);\n    return *this;\n  }\n  SseUint32& operator>>=(int n) {\n    v = _mm_srli_epi32(v, n);\n    return *this;\n  }\n\n  // Arithmetic (non-member friends for symmetric implicit conversions).\n  friend SseUint32 operator+(SseUint32 a, SseUint32 b) {\n    return _mm_add_epi32(a.v, b.v);\n  }\n  friend SseUint32 operator-(SseUint32 a, SseUint32 b) {\n    return _mm_sub_epi32(a.v, b.v);\n  }\n  friend SseUint32 operator*(SseUint32 a, SseUint32 b) {\n    return _mm_mullo_epi32(a.v, b.v);\n  }\n\n  // Bitwise.\n  friend SseUint32 operator&(SseUint32 a, SseUint32 b) {\n    return _mm_and_si128(a.v, b.v);\n  }\n  friend SseUint32 operator|(SseUint32 a, SseUint32 b) {\n    return _mm_or_si128(a.v, b.v);\n  }\n  friend SseUint32 operator^(SseUint32 a, SseUint32 b) {\n    return _mm_xor_si128(a.v, b.v);\n  }\n\n  friend SseUint32 operator~(SseUint32 a) {\n    return _mm_xor_si128(a.v, _mm_set1_epi32(-1));\n  }\n\n  // Unsigned comparisons need XOR with sign bit to convert to signed domain.\n  friend SseUint32 operator==(SseUint32 a, SseUint32 b) {\n    return _mm_cmpeq_epi32(a.v, b.v);\n  }\n  friend SseUint32 operator!=(SseUint32 a, SseUint32 b) {\n    return _mm_xor_si128(_mm_cmpeq_epi32(a.v, b.v), _mm_set1_epi32(-1));\n  }\n  friend SseUint32 operator>(SseUint32 a, SseUint32 b) {\n    __m128i bias = _mm_set1_epi32(static_cast<int32_t>(0x80000000u));\n    return _mm_cmpgt_epi32(_mm_xor_si128(a.v, bias), _mm_xor_si128(b.v, bias));\n  }\n  friend SseUint32 operator<(SseUint32 a, SseUint32 b) {\n    return b > a;\n  }\n\n  friend SseUint32 operator!(SseUint32 a) {\n    return _mm_cmpeq_epi32(a.v, _mm_setzero_si128());\n  }\n};\n\n// SseFloat ↔ SseInt32 conversion.\ninline SseFloat::SseFloat(SseInt32 i) : v(_mm_cvtepi32_ps(i.v)) {}\n\n// SseInt32 ↔ SseUint32 reinterpret (no-op on __m128i).\ninline SseInt32::SseInt32(SseUint32 u) : v(u.v) {}\n\n// Map raw __m128 to SseFloat for SimdTypeFor.\ntemplate <>\nstruct SimdTypeFor<__m128> {\n  using type = SseFloat;\n};\n\n// --- bit_cast specializations ---\n\ntemplate <>\ninline SseInt32 bit_cast<SseInt32>(const SseFloat& f) noexcept {\n  return _mm_castps_si128(f.v);\n}\ntemplate <>\ninline SseUint32 bit_cast<SseUint32>(const SseFloat& f) noexcept {\n  return _mm_castps_si128(f.v);\n}\ntemplate <>\ninline SseFloat bit_cast<SseFloat>(const SseInt32& i) noexcept {\n  return _mm_castsi128_ps(i.v);\n}\ntemplate <>\ninline SseFloat bit_cast<SseFloat>(const SseUint32& u) noexcept {\n  return _mm_castsi128_ps(u.v);\n}\ntemplate <>\ninline SseInt32 bit_cast<SseInt32>(const SseUint32& u) noexcept {\n  return u.v;\n}\ntemplate <>\ninline SseUint32 bit_cast<SseUint32>(const SseInt32& i) noexcept {\n  return i.v;\n}\n\n// --- FloatTraits<SseFloat> ---\n\ntemplate <>\nstruct FloatTraits<SseFloat> {\n  using IntType = SseInt32;\n  using UintType = SseUint32;\n  using BoolType = SseFloat; // Float comparison masks\n\n  static constexpr uint32_t kOne = 0x3f800000;\n  static constexpr float kMagic = 12582912.f;\n  static constexpr bool kBoolIsMask = true;\n\n  static DISPENSO_INLINE SseFloat sqrt(SseFloat x) {\n    return _mm_sqrt_ps(x.v);\n  }\n\n  static DISPENSO_INLINE SseFloat rcp(SseFloat x) {\n    return _mm_rcp_ps(x.v);\n  }\n\n  static DISPENSO_INLINE SseFloat fma(SseFloat a, SseFloat b, SseFloat c) {\n#if defined(__FMA__)\n    return _mm_fmadd_ps(a.v, b.v, c.v);\n#else\n    return _mm_add_ps(_mm_mul_ps(a.v, b.v), c.v);\n#endif\n  }\n\n  // conditional: select x where mask is true, y where false.\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(SseFloat mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg conditional(SseInt32 mask, Arg x, Arg y);\n\n  template <typename Arg>\n  static DISPENSO_INLINE Arg apply(SseFloat mask, Arg x);\n\n  static DISPENSO_INLINE SseFloat min(SseFloat a, SseFloat b) {\n    return _mm_min_ps(a.v, b.v);\n  }\n\n  static DISPENSO_INLINE SseFloat max(SseFloat a, SseFloat b) {\n    return _mm_max_ps(a.v, b.v);\n  }\n};\n\n// conditional specializations.\ntemplate <>\ninline SseFloat FloatTraits<SseFloat>::conditional(SseFloat mask, SseFloat x, SseFloat y) {\n  return _mm_blendv_ps(y.v, x.v, mask.v);\n}\ntemplate <>\ninline SseInt32 FloatTraits<SseFloat>::conditional(SseFloat mask, SseInt32 x, SseInt32 y) {\n  return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(y.v), _mm_castsi128_ps(x.v), mask.v));\n}\ntemplate <>\ninline SseUint32 FloatTraits<SseFloat>::conditional(SseFloat mask, SseUint32 x, SseUint32 y) {\n  return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(y.v), _mm_castsi128_ps(x.v), mask.v));\n}\n\ntemplate <>\ninline SseFloat FloatTraits<SseFloat>::conditional(SseInt32 mask, SseFloat x, SseFloat y) {\n  return _mm_blendv_ps(y.v, x.v, _mm_castsi128_ps(mask.v));\n}\ntemplate <>\ninline SseInt32 FloatTraits<SseFloat>::conditional(SseInt32 mask, SseInt32 x, SseInt32 y) {\n  return _mm_castps_si128(\n      _mm_blendv_ps(_mm_castsi128_ps(y.v), _mm_castsi128_ps(x.v), _mm_castsi128_ps(mask.v)));\n}\ntemplate <>\ninline SseUint32 FloatTraits<SseFloat>::conditional(SseInt32 mask, SseUint32 x, SseUint32 y) {\n  return _mm_castps_si128(\n      _mm_blendv_ps(_mm_castsi128_ps(y.v), _mm_castsi128_ps(x.v), _mm_castsi128_ps(mask.v)));\n}\n\n// apply: mask & x (bitwise AND).\ntemplate <>\ninline SseFloat FloatTraits<SseFloat>::apply(SseFloat mask, SseFloat x) {\n  return _mm_and_ps(mask.v, x.v);\n}\ntemplate <>\ninline SseInt32 FloatTraits<SseFloat>::apply(SseFloat mask, SseInt32 x) {\n  return _mm_and_si128(_mm_castps_si128(mask.v), x.v);\n}\ntemplate <>\ninline SseUint32 FloatTraits<SseFloat>::apply(SseFloat mask, SseUint32 x) {\n  return _mm_and_si128(_mm_castps_si128(mask.v), x.v);\n}\n\ntemplate <>\nstruct FloatTraits<SseInt32> {\n  using IntType = SseInt32;\n};\n\ntemplate <>\nstruct FloatTraits<SseUint32> {\n  using IntType = SseUint32;\n};\n\n// --- Util function overloads for SSE types ---\n\nDISPENSO_INLINE SseFloat floor_small(SseFloat x) {\n  return _mm_floor_ps(x.v);\n}\n\nDISPENSO_INLINE SseInt32 convert_to_int_trunc(SseFloat f) {\n  return _mm_cvttps_epi32(f.v);\n}\n\nDISPENSO_INLINE SseInt32 convert_to_int_trunc_safe(SseFloat f) {\n  SseInt32 fi = bit_cast<SseInt32>(f);\n  SseInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & SseInt32(_mm_cvttps_epi32(f.v));\n}\n\nDISPENSO_INLINE SseInt32 convert_to_int(SseFloat f) {\n  // _mm_cvtps_epi32 uses round-to-nearest-even.\n  // Mask non-normals to 0 to avoid undefined behavior.\n  SseInt32 fi = bit_cast<SseInt32>(f);\n  SseInt32 norm = (fi & 0x7f800000) != 0x7f800000;\n  return norm & SseInt32(_mm_cvtps_epi32(f.v));\n}\n\ntemplate <>\nDISPENSO_INLINE SseFloat min<SseFloat>(SseFloat x, SseFloat mn) {\n  // Ordering: if x is NaN, result is mn (second operand).\n  return _mm_min_ps(x.v, mn.v);\n}\n\ntemplate <>\nDISPENSO_INLINE SseFloat clamp_allow_nan<SseFloat>(SseFloat x, SseFloat mn, SseFloat mx) {\n  return _mm_max_ps(mn.v, _mm_min_ps(mx.v, x.v));\n}\n\ntemplate <>\nDISPENSO_INLINE SseFloat clamp_no_nan<SseFloat>(SseFloat x, SseFloat mn, SseFloat mx) {\n  return _mm_max_ps(mn.v, _mm_min_ps(x.v, mx.v));\n}\n\ntemplate <>\nDISPENSO_INLINE SseFloat gather<SseFloat>(const float* table, SseInt32 index) {\n  alignas(16) int32_t idx[4];\n  _mm_store_si128(reinterpret_cast<__m128i*>(idx), index.v);\n  return _mm_set_ps(table[idx[3]], table[idx[2]], table[idx[1]], table[idx[0]]);\n}\n\nDISPENSO_INLINE SseInt32 int_div_by_3(SseInt32 i) {\n  // Multiply each lane by 0x55555556 and take the high 32 bits.\n  // Process even and odd lanes separately since _mm_mul_epu32 only uses lanes 0,2.\n  __m128i multiplier = _mm_set1_epi32(0x55555556);\n  // Even lanes (0, 2).\n  __m128i even = _mm_srli_epi64(_mm_mul_epu32(i.v, multiplier), 32);\n  // Odd lanes (1, 3): shift right by 32 bits to put odd lanes in even positions.\n  __m128i i_odd = _mm_srli_epi64(i.v, 32);\n  __m128i odd = _mm_srli_epi64(_mm_mul_epu32(i_odd, multiplier), 32);\n  odd = _mm_slli_epi64(odd, 32);\n  // Blend even and odd results.\n  return _mm_blend_epi16(even, odd, 0xCC); // 0xCC = 11001100b selects odd from odd\n}\n\n// nonnormal/nonnormalOrZero: return SseInt32 masks for SSE types.\nDISPENSO_INLINE SseInt32 nonnormal(SseInt32 i) {\n  return (i & 0x7f800000) == 0x7f800000;\n}\n\nDISPENSO_INLINE SseInt32 nonnormalOrZero(SseInt32 i) {\n  auto m = i & 0x7f800000;\n  return (m == 0x7f800000) | (m == 0);\n}\n\nDISPENSO_INLINE SseInt32 nonnormal(SseFloat f) {\n  return nonnormal(bit_cast<SseInt32>(f));\n}\n\n// any_true: reduce SIMD mask to scalar bool (true if any lane is set).\nDISPENSO_INLINE bool any_true(SseInt32 mask) {\n  return _mm_movemask_ps(_mm_castsi128_ps(mask.v)) != 0;\n}\n\nDISPENSO_INLINE SseFloat signof(SseFloat x) {\n  SseUint32 xi = bit_cast<SseUint32>(x);\n  return bit_cast<SseFloat>((xi & 0x80000000u) | FloatTraits<SseFloat>::kOne);\n}\n\nDISPENSO_INLINE SseInt32 signofi(SseInt32 i) {\n  return SseInt32(1) - (SseInt32(2) & (i < SseInt32(0)));\n}\n\n// nbool_as_one: 0 if mask is true (all-ones), 1 if false (all-zeros).\ntemplate <>\nDISPENSO_INLINE SseFloat nbool_as_one<SseFloat, SseFloat>(SseFloat b) {\n  // ~mask & 1.0f bits\n  return bit_cast<SseFloat>(\n      SseInt32(_mm_andnot_si128(_mm_castps_si128(b.v), _mm_set1_epi32(0x3f800000))));\n}\n\ntemplate <>\nDISPENSO_INLINE SseInt32 nbool_as_one<SseInt32, SseFloat>(SseFloat b) {\n  return _mm_andnot_si128(_mm_castps_si128(b.v), _mm_set1_epi32(1));\n}\n\ntemplate <>\nDISPENSO_INLINE SseInt32 nbool_as_one<SseInt32, SseInt32>(SseInt32 b) {\n  return _mm_andnot_si128(b.v, _mm_set1_epi32(1));\n}\n\n// bool_as_one: 1 if mask is true, 0 if false.\ntemplate <>\nDISPENSO_INLINE SseFloat bool_as_one<SseFloat, SseFloat>(SseFloat b) {\n  return bit_cast<SseFloat>(\n      SseInt32(_mm_and_si128(_mm_castps_si128(b.v), _mm_set1_epi32(0x3f800000))));\n}\n\ntemplate <>\nDISPENSO_INLINE SseInt32 bool_as_one<SseInt32, SseFloat>(SseFloat b) {\n  return _mm_and_si128(_mm_castps_si128(b.v), _mm_set1_epi32(1));\n}\n\n// bool_as_mask: for SIMD masks, identity (already a mask).\ntemplate <>\nDISPENSO_INLINE SseInt32 bool_as_mask<SseInt32, SseFloat>(SseFloat b) {\n  return _mm_castps_si128(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE SseInt32 bool_as_mask<SseInt32, SseInt32>(SseInt32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE SseInt32 bool_as_mask<SseInt32, SseUint32>(SseUint32 b) {\n  return b.v;\n}\n\ntemplate <>\nDISPENSO_INLINE SseUint32 bool_as_mask<SseUint32, SseFloat>(SseFloat b) {\n  return _mm_castps_si128(b.v);\n}\n\ntemplate <>\nDISPENSO_INLINE SseUint32 bool_as_mask<SseUint32, SseUint32>(SseUint32 b) {\n  return b;\n}\n\ntemplate <>\nDISPENSO_INLINE SseUint32 bool_as_mask<SseUint32, SseInt32>(SseInt32 b) {\n  return b.v;\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n#endif // defined(__SSE4_1__)\n"
  },
  {
    "path": "dispenso/fast_math/simd.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Convenience header that provides DefaultSimdFloat — the widest available\n// SIMD float type for the current platform. Include this header and use\n// DefaultSimdFloat in generic code that should auto-vectorize to the best\n// available SIMD width.\n//\n// Example:\n//   #include <dispenso/fast_math/simd.h>\n//   using F = dispenso::fast_math::DefaultSimdFloat;\n//   F result = dispenso::fast_math::sin(F(1.0f));\n\n#pragma once\n\n// DefaultSimdFloat is defined in util.h (after SIMD backend includes).\n// This header just pulls in fast_math.h which includes util.h.\n#include <dispenso/fast_math/fast_math.h>\n"
  },
  {
    "path": "dispenso/fast_math/util.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <cstdint>\n#include <tuple>\n\n#if defined(__SSE__) || defined(__AVX__)\n#include <immintrin.h>\n#endif // __SSE__\n\n#include <cstring>\n#include <type_traits>\n\n#include \"float_traits.h\"\n\nnamespace dispenso {\nnamespace fast_math {\n\n// Reinterpret the bits of `src` as type `To`. Equivalent to std::bit_cast (C++20).\ntemplate <class To, class From>\nDISPENSO_INLINE std::enable_if_t<\n    sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> &&\n        std::is_trivially_copyable_v<To>,\n    To>\nbit_cast(const From& src) noexcept {\n  static_assert(\n      std::is_default_constructible_v<To>,\n      \"This implementation additionally requires \"\n      \"destination type to be default constructible\");\n\n  To dst;\n  memcpy(&dst, &src, sizeof(To));\n  return dst;\n}\n\n// Return the ULP distance between two floats. Denormals are treated as zero.\n// Handles mixed-sign comparisons correctly by mapping IEEE 754 bit patterns\n// to a linear integer representation where negative floats map to negative integers.\nDISPENSO_INLINE uint32_t float_distance(float a, float b) {\n  uint32_t ai = bit_cast<uint32_t>(a);\n  uint32_t bi = bit_cast<uint32_t>(b);\n\n  // Handle denormal values as zero\n  ai = ((ai & 0x7f800000) == 0) ? 0 : ai;\n  bi = ((bi & 0x7f800000) == 0) ? 0 : bi;\n\n  // Map to linear integer space: positive floats stay as-is,\n  // negative floats map to negative integers (sign-magnitude → two's complement).\n  auto toLinear = [](uint32_t bits) -> int32_t {\n    return (bits & 0x80000000u) ? static_cast<int32_t>(0x80000000u - bits)\n                                : static_cast<int32_t>(bits);\n  };\n  int32_t la = toLinear(ai);\n  int32_t lb = toLinear(bi);\n  int32_t diff = la - lb;\n  return static_cast<uint32_t>(diff < 0 ? -diff : diff);\n}\n\n// Absolute value: clears the sign bit.  Works for all float/SIMD types.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt fabs(Flt x) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return fabs(SimdType_t<Flt>(x)).v;\n  } else {\n    using Uint = UintType_t<Flt>;\n    return bit_cast<Flt>(bit_cast<Uint>(x) & Uint(0x7fffffff));\n  }\n}\n\n// Return +1.0 or -1.0 matching the sign bit of x. +0 gives +1, -0 gives -1.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt signof(Flt x) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return signof(SimdType_t<Flt>(x)).v;\n  } else {\n    using Uint = UintType_t<Flt>;\n    return bit_cast<Flt>((bit_cast<Uint>(x) & 0x80000000) | FloatTraits<Flt>::kOne);\n  }\n}\n\n// Integer sign: returns +1 for i >= 0, -1 for i < 0. Scalar version (kBoolIsMask=false).\ntemplate <typename Flt>\nDISPENSO_INLINE std::enable_if_t<!FloatTraits<Flt>::kBoolIsMask, IntType_t<Flt>> signofi(\n    IntType_t<Flt> i) {\n  return 1 - 2 * (i < 0);\n}\n\n// Integer sign: returns +1 for i >= 0, -1 for i < 0. SIMD mask version (kBoolIsMask=true).\ntemplate <typename Flt>\nDISPENSO_INLINE std::enable_if_t<FloatTraits<Flt>::kBoolIsMask, IntType_t<Flt>> signofi(\n    IntType_t<Flt> i) {\n  // Explicit IntType_t cast handles AVX-512 where (i < 0) returns Avx512Mask, not Avx512Int32.\n  auto neg = IntType_t<Flt>(i < 0);\n  return 1 - (2 & neg);\n}\n\n// True if the float (as int bits) has all exponent bits set (inf or NaN).\n// Returns bool for scalar types, SIMD lane mask for SIMD types.\ntemplate <typename Flt>\nDISPENSO_INLINE auto nonnormal(IntType_t<Flt> i) {\n  return (i & 0x7f800000) == 0x7f800000;\n}\n\n// True if the float (as int bits) is inf, NaN, or zero.\n// Returns bool for scalar types, SIMD lane mask for SIMD types.\ntemplate <typename Flt>\nDISPENSO_INLINE auto nonnormalOrZero(IntType_t<Flt> i) {\n  auto m = i & 0x7f800000;\n  return (m == 0x7f800000) | (m == 0);\n}\n\ntemplate <typename Flt>\nDISPENSO_INLINE auto nonnormal(Flt f) {\n  return nonnormal<Flt>(bit_cast<IntType_t<Flt>>(f));\n}\n\n// Truncate float toward zero, returning int. No inf/NaN guard — caller must\n// ensure inputs are finite (e.g. after range reduction by a finite constant).\n// Maps to cvttps2epi32 (SSE), vcvtq_s32_f32 (NEON), or (int)f (scalar).\ntemplate <typename Flt>\nDISPENSO_INLINE IntType_t<Flt> convert_to_int_trunc(Flt f) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return convert_to_int_trunc(SimdType_t<Flt>(f)).v;\n  } else {\n    return static_cast<IntType_t<Flt>>(f);\n  }\n}\n\n// Truncate float toward zero, returning int. Inf/NaN lanes are zeroed.\n// Use when the input may contain non-finite values.\ntemplate <typename Flt>\nDISPENSO_INLINE IntType_t<Flt> convert_to_int_trunc_safe(Flt f) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return convert_to_int_trunc_safe(SimdType_t<Flt>(f)).v;\n  } else {\n    auto fi = bit_cast<IntType_t<Flt>>(f);\n    if ((fi & 0x7f800000) == 0x7f800000) {\n      return 0;\n    }\n    return static_cast<IntType_t<Flt>>(f);\n  }\n}\n\n// Convert float to int using round-to-nearest-even (SSE cvtss2si semantics).\n// For non-normal inputs (inf/NaN), returns 0 to avoid undefined behavior.\ntemplate <typename Flt>\nDISPENSO_INLINE IntType_t<Flt> convert_to_int(Flt f) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return convert_to_int(SimdType_t<Flt>(f)).v;\n  } else {\n#if defined(__SSE__)\n    return _mm_cvtss_si32(_mm_set_ss(f));\n#else\n    // Round to nearest even via magic number addition, guard non-normals → 0.\n    auto fi = bit_cast<IntType_t<Flt>>(f);\n    if ((fi & 0x7f800000) == 0x7f800000) {\n      return 0;\n    }\n    constexpr float kMagic = FloatTraits<Flt>::kMagic; // 1.5f * 2^23\n    return static_cast<IntType_t<Flt>>((f + kMagic) - kMagic);\n#endif // __SSE__\n  }\n}\n\n// Convert float to int with round-to-nearest-even, clamping to [kMin, kMax].\n// For non-normal inputs (inf/NaN), returns 0 to avoid undefined behavior.\ntemplate <typename Flt, IntType_t<Flt> kMin, IntType_t<Flt> kMax>\nDISPENSO_INLINE IntType_t<Flt> convert_to_int_clamped(Flt f) {\n#if defined(__SSE4_1__)\n  static const __m128i kMn = _mm_set1_epi32(kMin);\n  static const __m128i kMx = _mm_set1_epi32(kMax);\n  __m128i i = _mm_cvtps_epi32(_mm_set_ss(f));\n  i = _mm_min_epi32(i, kMx);\n  i = _mm_max_epi32(i, kMn);\n  return _mm_cvtsi128_si32(i);\n#else\n  // Round to nearest even via magic number addition (same technique as rangeReduce),\n  // then clamp. Guard against non-normal inputs (inf/NaN) → return 0.\n  auto fi = bit_cast<IntType_t<Flt>>(f);\n  if ((fi & 0x7f800000) == 0x7f800000) {\n    return 0;\n  }\n  constexpr float kMagic = FloatTraits<Flt>::kMagic; // 1.5f * 2^23\n  auto rounded = static_cast<IntType_t<Flt>>((f + kMagic) - kMagic);\n  if (rounded > kMax)\n    return kMax;\n  if (rounded < kMin)\n    return kMin;\n  return rounded;\n#endif // __SSE4_1__\n}\n\n// Floor for values within integer range. Uses SSE4.1 roundss when available.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt floor_small(Flt x) {\n  if constexpr (!std::is_same_v<Flt, SimdType_t<Flt>>) {\n    return floor_small(SimdType_t<Flt>(x)).v;\n  } else {\n    IntType_t<Flt> i = x;\n    Flt xi = i;\n    if constexpr (FloatTraits<Flt>::kBoolIsMask) {\n      return i - ((x < xi) & 1);\n    } else {\n      return i - (x < xi) * 1;\n    }\n  }\n}\n\ntemplate <>\nDISPENSO_INLINE float floor_small(float x) {\n#if defined(__SSE4_1__)\n  __m128 f = _mm_set_ss(x);\n  __m128 r = _mm_floor_ss(f, f);\n  return _mm_cvtss_f32(r);\n#else\n  return std::floor(x);\n#endif // __SSE4_1__\n}\n\n// Minimum of x and mn. If x is NaN and mn is not, returns mn (relied-upon NaN behavior).\ntemplate <typename Flt>\nDISPENSO_INLINE Flt min(Flt x, Flt mn);\n\ntemplate <>\nDISPENSO_INLINE float min(float x, float mn) {\n#if defined(__SSE4_1__)\n  __m128 f = _mm_set_ss(x);\n  __m128 fmn = _mm_set_ss(mn);\n  // Ordering matters here for NaN behavior\n  __m128 r = _mm_min_ss(f, fmn);\n  return _mm_cvtss_f32(r);\n#else\n  return x < mn ? x : mn;\n#endif //__SSE4_1__\n}\n\n// Clamp x to [mn, mx]. If x is NaN, NaN propagates (result is NaN).\n// Use when NaN should signal an error rather than be silently clamped.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt clamp_allow_nan(Flt x, Flt mn, Flt mx);\n\ntemplate <>\nDISPENSO_INLINE float clamp_allow_nan(float x, float mn, float mx) {\n#if defined(__SSE4_1__)\n  __m128 f = _mm_set_ss(x);\n  __m128 fmn = _mm_set_ss(mn);\n  __m128 fmx = _mm_set_ss(mx);\n  // Ordering matters here for NaN behavior\n  __m128 r = _mm_max_ss(fmn, _mm_min_ss(fmx, f));\n  return _mm_cvtss_f32(r);\n#else\n  mx = (mx < x) ? mx : x;\n  return (mx < mn) ? mn : mx;\n#endif // __SSE4_1__\n}\n\n// Clamp x to [mn, mx]. If x is NaN, returns a value in [mn, mx] (NaN is suppressed).\n// Use when a valid output is required regardless of input.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt clamp_no_nan(Flt x, Flt mn, Flt mx);\n\ntemplate <>\nDISPENSO_INLINE float clamp_no_nan(float x, float mn, float mx) {\n#if defined(__SSE4_1__)\n  __m128 f = _mm_set_ss(x);\n  __m128 fmn = _mm_set_ss(mn);\n  __m128 fmx = _mm_set_ss(mx);\n  // Ordering matters here for NaN behavior\n  __m128 r = _mm_max_ss(fmn, _mm_min_ss(f, fmx));\n  return _mm_cvtss_f32(r);\n\n  // TODO: See vrndmq_f32 for ARM NEON\n\n#else\n  mx = (mx > x) ? x : mx;\n  return (mx > mn) ? mx : mn;\n#endif // __SSE4_1__\n}\n\n// Load table[index]. Scalar version is a plain array access; SIMD versions use gather instructions.\ntemplate <typename Flt>\nDISPENSO_INLINE Flt gather(const float* table, IntType_t<Flt> index);\n\ntemplate <>\nDISPENSO_INLINE float gather(const float* table, int32_t index) {\n  return table[index];\n}\n\n// Return 0 if b is true, 1 if b is false (negated bool as numeric).\ntemplate <typename T, typename BoolT>\nDISPENSO_INLINE T nbool_as_one(BoolT b);\ntemplate <>\nDISPENSO_INLINE float nbool_as_one<float, bool>(bool b) {\n  return b ? 0.0f : 1.0f;\n}\n\ntemplate <>\nDISPENSO_INLINE int32_t nbool_as_one<int32_t, bool>(bool b) {\n  return static_cast<int32_t>(!b);\n}\n\n// Return 1 if b is true, 0 if b is false (bool as numeric).\ntemplate <typename T, typename BoolT>\nDISPENSO_INLINE T bool_as_one(BoolT b);\ntemplate <>\nDISPENSO_INLINE float bool_as_one<float, bool>(bool b) {\n  return b ? 1.0f : 0.0f;\n}\n\ntemplate <>\nDISPENSO_INLINE int32_t bool_as_one<int32_t, bool>(bool b) {\n  return static_cast<int32_t>(b);\n}\n\n// Convert bool to bitmask: true → all-ones (0xFFFFFFFF), false → 0x0.\n// For SIMD types, this converts a lane mask to an integer mask for bitwise ops.\ntemplate <typename T, typename BoolT>\nDISPENSO_INLINE T bool_as_mask(BoolT b) {\n  T mask = b;\n  return ~(mask - 1);\n}\n\n// Return val if b is true, 0 otherwise. Uses bitwise AND via bool_as_mask.\ntemplate <typename T, typename BoolT>\nDISPENSO_INLINE T bool_apply_or_zero(BoolT b, T val) {\n  return bit_cast<T>(bool_as_mask<IntType_t<T>>(b) & bit_cast<IntType_t<T>>(val));\n}\n\n// True if x is an integer. Safe for all float values including large, inf, NaN.\n// All floats with |x| >= 2^23 are integers (mantissa has no fractional bits).\n// For |x| < 2^23, floor_small(x) is valid (no int overflow).\ntemplate <typename Flt>\nDISPENSO_INLINE BoolType_t<Flt> float_is_int(Flt x) {\n  auto ax = fabs(x);\n  return (ax >= Flt(8388608.0f)) | (floor_small(x) == x);\n}\n\n// True if x is an odd integer.\n// For |x| >= 2^24: ULP >= 2, so only even integers are representable → always false.\ntemplate <typename Flt>\nDISPENSO_INLINE BoolType_t<Flt> float_is_odd(Flt x) {\n  if constexpr (std::is_same_v<Flt, float>) {\n    return float_is_int(x) && !float_is_int(x * 0.5f);\n  } else {\n    return float_is_int(x) & !float_is_int(x * Flt(0.5f));\n  }\n}\n\n// Fast integer division by 3 using multiply-and-shift. Used in cbrt magic constant computation.\nDISPENSO_INLINE int32_t int_div_by_3(int32_t i) {\n  return static_cast<int32_t>((uint64_t(i) * 0x55555556) >> 32);\n}\n\n// ---------------------------------------------------------------------------\n// Polynomial evaluation: hornerEval, estrinEval, polyEval\n// ---------------------------------------------------------------------------\n//\n// All take coefficients in HIGH-to-LOW order (highest degree first):\n//   polyEval(x, cn, cn-1, ..., c1, c0) = cn*x^n + cn-1*x^(n-1) + ... + c1*x + c0\n//\n// This matches the natural Horner evaluation order and the existing hand-written\n// FMA chains in fast_math. For odd/even polynomial forms like tanh(x) = x*(1+x²*Q(x²)),\n// compose as: x * (1 + x2 * polyEval(x2, qn, ..., q1, q0)).\n\nnamespace detail {\n\n// --- Horner evaluation ---\n// Sequential FMA chain, optimal for low-ILP targets (GPU, scalar, narrow SIMD).\n// Degree N polynomial = N FMAs.\n\ntemplate <typename Flt>\nDISPENSO_INLINE Flt hornerImpl(Flt, Flt accum) {\n  return accum;\n}\n\ntemplate <typename Flt, typename... Cs>\nDISPENSO_INLINE Flt hornerImpl(Flt x, Flt accum, Flt next, Cs... rest) {\n  return hornerImpl(x, FloatTraits<Flt>::fma(accum, x, next), rest...);\n}\n\n// --- Estrin evaluation ---\n// Tree-reduces paired coefficients at each level, cutting critical-path depth\n// from N to ceil(log2(N+1)) at the cost of extra multiplies for x powers.\n// Better for wide SIMD with high ILP (AVX, AVX-512).\n//\n// Generic peel-and-recurse via tuples. At each level:\n//   1. Pair adjacent values: (a,b) → fma(a, xp, b)\n//   2. Carry unpaired odd element\n//   3. Recurse with xp² and the paired results\n//\n// All tuple operations (make_tuple, tuple_cat, apply) are eliminated by the\n// optimizer — verified to produce identical assembly to hand-written FMA trees\n// with clang 21, GCC 11, and GCC 15 at -O2.\n\ntemplate <typename Flt>\nstruct EstrinImpl {\n  // Base cases\n  DISPENSO_INLINE static Flt reduce(Flt, std::tuple<Flt> done) {\n    return std::get<0>(done);\n  }\n\n  DISPENSO_INLINE static Flt reduce(Flt xp, std::tuple<Flt, Flt> done) {\n    return FloatTraits<Flt>::fma(std::get<0>(done), xp, std::get<1>(done));\n  }\n\n  // General: unpack tuple, pair all elements at this level, recurse\n  template <typename... Done>\n  DISPENSO_INLINE static Flt reduce(Flt xp, std::tuple<Done...> done) {\n    return std::apply([xp](auto... ds) { return pairLevel(xp, std::tuple<>{}, ds...); }, done);\n  }\n\n  // Done pairing at this level — recurse with xp²\n  template <typename... Paired>\n  DISPENSO_INLINE static Flt pairLevel(Flt xp, std::tuple<Paired...> paired) {\n    return reduce(xp * xp, paired);\n  }\n\n  // Odd leftover — carry forward unpaired\n  template <typename... Paired>\n  DISPENSO_INLINE static Flt pairLevel(Flt xp, std::tuple<Paired...> paired, Flt a) {\n    return reduce(xp * xp, std::tuple_cat(paired, std::make_tuple(a)));\n  }\n\n  // Peel two from front, pair via FMA, accumulate into paired tuple\n  template <typename... Paired, typename... Rest>\n  DISPENSO_INLINE static Flt\n  pairLevel(Flt xp, std::tuple<Paired...> paired, Flt a, Flt b, Rest... rest) {\n    return pairLevel(\n        xp, std::tuple_cat(paired, std::make_tuple(FloatTraits<Flt>::fma(a, xp, b))), rest...);\n  }\n};\n\n} // namespace detail\n\n// Horner evaluation: hornerEval(x, cn, cn-1, ..., c0) = ((cn*x + cn-1)*x + ...)*x + c0\n// Coefficients HIGH-to-LOW (highest degree first).\n// Flt is deduced from x; coefficients are converted to Flt internally.\ntemplate <typename Flt, typename C0, typename... Cs>\nDISPENSO_INLINE Flt hornerEval(Flt x, C0 cn, Cs... rest) {\n  return detail::hornerImpl(x, Flt(cn), Flt(rest)...);\n}\n\n// Estrin evaluation: same semantics as hornerEval, but uses tree-reduction\n// for lower critical-path depth (ceil(log2(N)) vs N dependent FMAs).\n// Coefficients HIGH-to-LOW.\ntemplate <typename Flt, typename C0, typename... Cs>\nDISPENSO_INLINE Flt estrinEval(Flt x, C0 cn, Cs... rest) {\n  return detail::EstrinImpl<Flt>::reduce(x, std::make_tuple(Flt(cn), Flt(rest)...));\n}\n\n// Platform-adaptive polynomial evaluation.\n// Uses Estrin on CPU (tree reduction for ILP on wide SIMD), Horner on GPU\n// (sequential FMA chain, no wasted registers on in-order pipelines).\n// Use polyEval only at call sites where Estrin has been measured beneficial.\n// Use hornerEval directly for accuracy-sensitive polynomials where Estrin's\n// different rounding order would regress ULP.\n// Coefficients HIGH-to-LOW: polyEval(x, cn, ..., c0).\ntemplate <typename Flt, typename C0, typename... Cs>\nDISPENSO_INLINE Flt polyEval(Flt x, C0 cn, Cs... rest) {\n#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)\n  return hornerEval(x, cn, rest...);\n#else\n  return estrinEval(x, cn, rest...);\n#endif\n}\n\n} // namespace fast_math\n} // namespace dispenso\n\n// Auto-detect SIMD backends and include FloatTraits specializations.\n#if defined(__SSE4_1__)\n#include <dispenso/fast_math/float_traits_x86.h>\n#endif\n\n#if defined(__AVX2__)\n#include <dispenso/fast_math/float_traits_avx.h>\n#endif\n\n#if defined(__AVX512F__)\n#include <dispenso/fast_math/float_traits_avx512.h>\n#endif\n\n#if defined(__aarch64__)\n#include <dispenso/fast_math/float_traits_neon.h>\n#endif\n\n#if __has_include(\"hwy/highway.h\")\n#include <dispenso/fast_math/float_traits_hwy.h>\n#endif\n\nnamespace dispenso {\nnamespace fast_math {\n\n// Best available SIMD float type for the current platform.\n// Prefer native intrinsic wrappers over Highway for lower overhead.\n// Highway is a fallback for platforms without a native wrapper.\n#if defined(__aarch64__)\nusing DefaultSimdFloat = NeonFloat;\n#elif defined(__AVX512F__)\nusing DefaultSimdFloat = Avx512Float;\n#elif defined(__AVX2__)\nusing DefaultSimdFloat = AvxFloat;\n#elif defined(__SSE4_1__)\nusing DefaultSimdFloat = SseFloat;\n#elif __has_include(\"hwy/highway.h\")\nusing DefaultSimdFloat = HwyFloat;\n#else\nusing DefaultSimdFloat = float;\n#endif\n\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/for_each.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file for_each.h\n * @ingroup group_parallel\n * Functions for performing parallel for_each over iterables.  This intends to more-or-less\n * mimic std::for_each, with a possible (Concurrent)TaskSet passed in for external wait capability,\n * and ForEachOptions for controlling the wait behavior and limiting of parallelism.\n **/\n\n#pragma once\n\n#include <algorithm>\n#include <iterator>\n\n#include <dispenso/detail/per_thread_info.h>\n#include <dispenso/small_vector.h>\n#include <dispenso/task_set.h>\n\nnamespace dispenso {\n\n#if DISPENSO_HAS_CONCEPTS\n/**\n * @concept ForEachFunc\n * @brief A callable suitable for for_each operations.\n *\n * The callable must be invocable with a reference to the iterator's value type.\n **/\ntemplate <typename F, typename Iter>\nconcept ForEachFunc = std::invocable<F, decltype(*std::declval<Iter>())>;\n#endif // DISPENSO_HAS_CONCEPTS\n\n/**\n * A set of options to control for_each\n **/\nstruct ForEachOptions {\n  /**\n   * The maximum number of threads to use.  This can be used to limit the number of threads below\n   * the number associated with the TaskSet's thread pool to control the degree of concurrency.\n   * Setting maxThreads to zero or one will result in serial operation.\n   **/\n  uint32_t maxThreads = std::numeric_limits<int32_t>::max();\n  /**\n   * Specify whether the return of the for_each signifies the work is complete.  If the\n   * for_each is initiated without providing a TaskSet, the for_each will always wait.\n   *\n   * @note If wait is true, the calling thread will always participate in computation.  If this is\n   * not desired, pass wait as false, and wait manually outside of the for_each on the passed\n   * TaskSet.\n   **/\n  bool wait = true;\n};\n\nnamespace detail {\n\n// Random-access iterators: compute chunk boundaries arithmetically, avoiding SmallVector.\ntemplate <typename TaskSetT, typename Iter, typename F>\nvoid for_each_n_schedule(\n    TaskSetT& tasks,\n    Iter start,\n    F&& f,\n    ssize_t numThreads,\n    size_t chunkSize,\n    ssize_t transitionIdx,\n    size_t smallChunkSize,\n    const ForEachOptions& options,\n    std::random_access_iterator_tag) {\n  ssize_t numToSchedule = options.wait ? numThreads - 1 : numThreads;\n\n  if (numToSchedule > 0) {\n    tasks.scheduleBulk(\n        static_cast<size_t>(numToSchedule),\n        [start, &f, chunkSize, smallChunkSize, transitionIdx](size_t idx) {\n          ssize_t sidx = static_cast<ssize_t>(idx);\n          ssize_t offset;\n          ssize_t thisChunkSize;\n          if (sidx < transitionIdx) {\n            offset = sidx * static_cast<ssize_t>(chunkSize);\n            thisChunkSize = static_cast<ssize_t>(chunkSize);\n          } else {\n            offset = transitionIdx * static_cast<ssize_t>(chunkSize) +\n                (sidx - transitionIdx) * static_cast<ssize_t>(smallChunkSize);\n            thisChunkSize = static_cast<ssize_t>(smallChunkSize);\n          }\n          Iter s = start + offset;\n          Iter e = s + thisChunkSize;\n          return [s, e, f]() {\n            auto recurseInfo = PerPoolPerThreadInfo::parForRecurse();\n            for (Iter it = s; it != e; ++it) {\n              f(*it);\n            }\n          };\n        });\n  }\n\n  if (options.wait) {\n    ssize_t lastIdx = numThreads - 1;\n    ssize_t offset;\n    ssize_t thisChunkSize;\n    if (lastIdx < transitionIdx) {\n      offset = lastIdx * static_cast<ssize_t>(chunkSize);\n      thisChunkSize = static_cast<ssize_t>(chunkSize);\n    } else {\n      offset = transitionIdx * static_cast<ssize_t>(chunkSize) +\n          (lastIdx - transitionIdx) * static_cast<ssize_t>(smallChunkSize);\n      thisChunkSize = static_cast<ssize_t>(smallChunkSize);\n    }\n    Iter lastStart = start + offset;\n    Iter lastEnd = lastStart + thisChunkSize;\n    for (Iter it = lastStart; it != lastEnd; ++it) {\n      f(*it);\n    }\n    tasks.wait();\n  }\n}\n\n// Non-random-access iterators: pre-compute boundary iterators into SmallVector.\ntemplate <typename TaskSetT, typename Iter, typename F, typename IterCategory>\nvoid for_each_n_schedule(\n    TaskSetT& tasks,\n    Iter start,\n    F&& f,\n    ssize_t numThreads,\n    size_t chunkSize,\n    ssize_t transitionIdx,\n    size_t smallChunkSize,\n    const ForEachOptions& options,\n    IterCategory) {\n  SmallVector<Iter, 64> boundaries;\n  boundaries.reserve(static_cast<size_t>(numThreads) + 1);\n  boundaries.push_back(start);\n  for (ssize_t t = 0; t < numThreads; ++t) {\n    size_t cs = (t < transitionIdx) ? chunkSize : smallChunkSize;\n    Iter next = boundaries[t];\n    std::advance(next, static_cast<ptrdiff_t>(cs));\n    boundaries.push_back(next);\n  }\n\n  ssize_t numToSchedule = options.wait ? numThreads - 1 : numThreads;\n\n  if (numToSchedule > 0) {\n    tasks.scheduleBulk(static_cast<size_t>(numToSchedule), [&boundaries, &f](size_t idx) {\n      return [s = boundaries[idx], e = boundaries[idx + 1], f]() {\n        auto recurseInfo = PerPoolPerThreadInfo::parForRecurse();\n        for (Iter it = s; it != e; ++it) {\n          f(*it);\n        }\n      };\n    });\n  }\n\n  if (options.wait) {\n    for (Iter it = boundaries[numThreads - 1]; it != boundaries[numThreads]; ++it) {\n      f(*it);\n    }\n    tasks.wait();\n  }\n}\n\n} // namespace detail\n\n/**\n * A function like std::for_each_n, but where the function is invoked in parallel across the passed\n * range.\n *\n * @param tasks The task set to schedule the for_each on.\n * @param start The iterator for the start of the range.\n * @param n The length of the range.\n * @param f The function to execute in parallel.  This is a unary function that must be capable of\n * taking dereference of Iter.\n * @param options See ForEachOptions for details.\n **/\ntemplate <typename TaskSetT, typename Iter, typename F>\nDISPENSO_REQUIRES(ForEachFunc<F, Iter>)\nvoid for_each_n(TaskSetT& tasks, Iter start, size_t n, F&& f, ForEachOptions options = {}) {\n  // TODO(bbudge): With options.maxThreads, we might want to allow a small fanout factor in\n  // recursive case?\n  if (!n || !options.maxThreads || detail::PerPoolPerThreadInfo::isParForRecursive(&tasks.pool())) {\n    for (size_t i = 0; i < n; ++i) {\n      f(*start);\n      ++start;\n    }\n    if (options.wait) {\n      tasks.wait();\n    }\n    return;\n  }\n\n  // 0 indicates serial execution per API spec\n  int32_t maxThreads = std::max<int32_t>(options.maxThreads, 1);\n\n  ssize_t numThreads = std::min<ssize_t>(tasks.numPoolThreads() + options.wait, maxThreads);\n  // Reduce threads used if they exceed work to be done.\n  numThreads = std::min<ssize_t>(numThreads, n);\n\n  auto chunking = detail::staticChunkSize(n, numThreads);\n  size_t chunkSize = chunking.ceilChunkSize;\n\n  bool perfectlyChunked = chunking.transitionTaskIndex == numThreads;\n  ssize_t transitionIdx = chunking.transitionTaskIndex;\n  size_t smallChunkSize = chunkSize - !perfectlyChunked;\n\n  detail::for_each_n_schedule(\n      tasks,\n      start,\n      std::forward<F>(f),\n      numThreads,\n      chunkSize,\n      transitionIdx,\n      smallChunkSize,\n      options,\n      typename std::iterator_traits<Iter>::iterator_category{});\n}\n\n/**\n * A function like std::for_each_n, but where the function is invoked in parallel across the passed\n * range.\n *\n * @param start The iterator for the start of the range.\n * @param n The length of the range.\n * @param f The function to execute in parallel.  This is a unary function that must be capable of\n * taking dereference of Iter.\n * @param options See ForEachOptions for details; however it should be noted that this function must\n * always wait, and therefore options.wait is ignored.\n **/\ntemplate <typename Iter, typename F>\nDISPENSO_REQUIRES(ForEachFunc<F, Iter>)\nvoid for_each_n(Iter start, size_t n, F&& f, ForEachOptions options = {}) {\n  TaskSet taskSet(globalThreadPool());\n  options.wait = true;\n  for_each_n(taskSet, start, n, std::forward<F>(f), options);\n}\n\n/**\n * A function like std::for_each, but where the function is invoked in parallel across the passed\n * range.\n *\n * @param tasks The task set to schedule the for_each on.\n * @param start The iterator for the start of the range.\n * @param end The iterator for the end of the range.\n * @param f The function to execute in parallel.  This is a unary function that must be capable of\n * taking dereference of Iter.\n * @param options See ForEachOptions for details.\n **/\ntemplate <typename TaskSetT, typename Iter, typename F>\nDISPENSO_REQUIRES(ForEachFunc<F, Iter>)\nvoid for_each(TaskSetT& tasks, Iter start, Iter end, F&& f, ForEachOptions options = {}) {\n  for_each_n(tasks, start, std::distance(start, end), std::forward<F>(f), options);\n}\n\n/**\n * A function like std::for_each, but where the function is invoked in parallel across the passed\n * range.\n *\n * @param start The iterator for the start of the range.\n * @param end The iterator for the end of the range.\n * @param f The function to execute in parallel.  This is a unary function that must be capable of\n * taking dereference of Iter.\n * @param options See ForEachOptions for details; however it should be noted that this function must\n * always wait, and therefore options.wait is ignored.\n **/\ntemplate <typename Iter, typename F>\nDISPENSO_REQUIRES(ForEachFunc<F, Iter>)\nvoid for_each(Iter start, Iter end, F&& f, ForEachOptions options = {}) {\n  for_each_n(start, std::distance(start, end), std::forward<F>(f), options);\n}\n\n// TODO(bbudge): Implement ranges versions for these in C++20 (currently not in an env where this\n// can be tested)\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/future.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file future.h\n * @ingroup group_async\n * A file providing Futures, as well as functionality for creating futures, and for how to invoke\n * Futures' closures.\n *\n * See https://en.cppreference.com/w/cpp/experimental/future for details on the API.\n **/\n\n#pragma once\n\n#include <functional>\n#include <vector>\n\n#include <dispenso/detail/future_impl.h>\n#include <dispenso/detail/result_of.h>\n#include <dispenso/schedulable.h>\n\nnamespace dispenso {\n\n// See https://en.cppreference.com/w/cpp/experimental/future for details on the API.\n\n// TODO(bbudge): Implement when_any(), ?unwrapping constructor? functionality.\n\n/**\n *  A <code>std::launch</code> policy specifying we won't force asynchronicity.  Opposite of\n * <code>std::launch::async</code>\n **/\nconstexpr std::launch kNotAsync = static_cast<std::launch>(0);\n/**\n * A <code>std::launch</code> policy specifying we won't allow <code>Future::wait_for</code> and\n * <code>Future::wait_util</code> to invoke the Future's underlying functor.  Opposite of\n * <code>std::launch::deferred</code>\n **/\nconstexpr std::launch kNotDeferred = static_cast<std::launch>(0);\n\n/**\n * A class that implements a hybrid of the interfaces for std::experimental::future, and\n * std::experimental::shared_future.  <code>Future</code> acts like a <code>shared_future</code>,\n * but includes the <code>share</code> function in order to enable generic code that may use the\n * function. See https://en.cppreference.com/w/cpp/experimental/future for more details on the API,\n * but some differences are notable.\n *\n * 1. <code>dispenso::Future</code> are created and set into executors through their constructor, or\n *    through <code>dispenso::async</code>\n * 2. <code>dispenso::future</code> can be shared around like\n *    <code>std::experimental::shared_future</code>, and wait/get functions may be called\n *    concurrently from multiple threads.\n *\n * Future is thread-safe to call into, with the usual caveats (one thread may not be calling\n * anything on the Future while another thread assigns to it or destructs it).  It is thread-safe to\n * assign or destruct on one copy of a Future while making calls on another copy of a Future\n * with the same backing state.\n *\n * Because Future is designed to work well with the dispenso TaskSet and ThreadPool, Future\n * aggressively work steals in <code>get</code> and <code>wait</code> functions.  This prevents\n * deadlock due to thread pool resource starvation, similar to how TaskSets avoid that flavor of\n * deadlock.  It is important to note that deadlock is still possible due to traditional cyclic\n * dependency, e.g. Future A and Future B which wait on each other.  Just as with a cyclic mutex\n * locking requirement, cyclic Future waits are considered programmer error.\n **/\ntemplate <typename Result>\nclass Future : detail::FutureBase<Result> {\n  using Base = detail::FutureBase<Result>;\n\n public:\n  /**\n   * Construct an invalid Future.\n   **/\n  Future() noexcept : Base() {}\n\n  /**\n   * Move constructor\n   *\n   * @param f The future to move from.\n   **/\n  Future(Future&& f) noexcept : Base(std::move(f)) {}\n  /** @copydoc Future(Future&&) */\n  Future(Base&& f) noexcept : Base(std::move(f)) {}\n\n  /**\n   * Copy construct a Future.\n   *\n   * @param f The existing future to reference.  This essentially increments the reference count on\n   * the future's backing state.\n   **/\n  Future(const Future& f) noexcept : Base(f) {}\n  /** @copydoc Future(const Future&) */\n  Future(const Base& f) noexcept : Base(f) {}\n\n  /**\n   * Construct a Future with callable and a schedulable (e.g. a ThreadPool or TaskSet), and ensure\n   * it is scheduled according to the launch policy.\n   *\n   * @param f a functor with signature <code>Result(void)</code> to be invoked in order for\n   * <code>get</code> to return a valid value.\n   * @param schedulable A <code>TaskSet</code>, <code>ThreadPool</code>, or similar type that has\n   * function <code>schedule</code> that takes a functor with signature <code>void()</code> and\n   * <code>ForceQueuingTag</code>.\n   * @param asyncPolicy If <code>std::launch::async</code>, the functor will be scheduled through to\n   * the underlying thread pool work queue.\n   * @param deferredPolicy If <code>std::launch::deferred</code>, <code>wait_for</code> and\n   * <code>wait_until</code> may invoke the functor from their calling thread.\n   **/\n  template <typename F, typename Schedulable>\n  Future(\n      F&& f,\n      Schedulable& schedulable,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred)\n      : Base(std::forward<F>(f), schedulable, asyncPolicy, deferredPolicy) {}\n\n  /**\n   * Move a Future\n   *\n   * @param f The Future whose backing state will be transferred to this Future.\n   **/\n  Future& operator=(Future&& f) noexcept {\n    Base::move(reinterpret_cast<Base&&>(f));\n    return *this;\n  }\n  /**\n   * Copy a Future, which increments the underlying state reference count.\n   *\n   * @param f The Future whose backing state will be referenced by this Future.\n   **/\n  Future& operator=(const Future& f) {\n    Base::copy(f);\n    return *this;\n  }\n\n  /**\n   * Destruct a Future.  This decrements the shared reference count (if any), and ensures the\n   * backing state is destroyed when no more references exist to the backing state.\n   **/\n  ~Future() = default;\n\n  /**\n   * Is this Future valid?\n   *\n   * @return <code>true</code> if the Future was constructed with a functor/schedulable, with result\n   * value, or indirectly from a Future that was constructed one of those ways.  <code>false</code>\n   * if the Future was constructed via the default constructor, or indrectly from a Future that was\n   * constructed that way.\n   **/\n  bool valid() const noexcept {\n    return Base::valid();\n  }\n\n  /**\n   * Is the Future ready?\n   *\n   * @return <code>true</code> if the value associated with this Future has already be computed, and\n   * <code>get</code> can return the value immediately.  Returns <code>false</code> if the functor\n   * is logically queued, or is in progress.\n   **/\n  bool is_ready() const {\n    return Base::is_ready();\n  }\n\n  /**\n   * Wait until <code>is_ready</code> is <code>true</code>.\n   *\n   * @note This function will invoke the functor if it is still logically queued.\n   **/\n  void wait() const {\n    Base::wait();\n  }\n\n  /**\n   * Wait until <code>is_ready</code> is <code>true</code> or until timing out.\n   *\n   * @param timeoutDuration The length of time to wait until timing out.  This is relative to the\n   * current point in time.\n   * @return <code>std::future_status::ready</code> if <code>get</code> can return immediately,\n   * <code>std::future_status::timeout</code> if the function timed out while waiting.\n   *\n   * @note This function may invoke the functor if it is still logically queued, and\n   * <code>std::launch::deferred</code> was specified at construction.\n   **/\n  template <class Rep, class Period>\n  std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeoutDuration) const {\n    return Base::wait_for(timeoutDuration);\n  }\n\n  /**\n   * Wait until <code>is_ready</code> is <code>true</code> or until timing out.\n   *\n   * @param timeoutTime The absolute time to wait until timing out.\n   * @return <code>std::future_status::ready</code> if <code>get</code> can return immediately,\n   * <code>std::future_status::timeout</code> if the function timed out while waiting.\n   *\n   * @note This function may invoke the functor if it is still logically queued, and\n   * <code>std::launch::deferred</code> was specified at construction.\n   **/\n  template <class Clock, class Duration>\n  std::future_status wait_until(const std::chrono::time_point<Clock, Duration>& timeoutTime) const {\n    return Base::wait_until(timeoutTime);\n  }\n\n  /**\n   * Provide a shared future.  <code>share</code> is here only to provide compatible api with\n   * <code>std::experimental::future</code>, but Future already works like std::shared_future.\n   **/\n  Future share() {\n    return std::move(*this);\n  }\n\n  /**\n   * Get the result of the future functor.  This function blocks until the result is ready.\n   *\n   * @return A const reference to the result's value.\n   **/\n  const Result& get() const {\n    wait();\n    return this->impl_->result();\n  }\n\n  /**\n   * Schedule a functor to be invoked upon reaching <code>is_ready</code> status, and return\n   * a future that will hold the result of the functor.\n   *\n   * @param f The functor to be executed whose result will be available in the returned\n   * <code>Future</code>.  This should have signature <code>Unpecified(Future<Result>&&)</code>.\n   * @param sched The Schedulable in which to run the functor.\n   * @param asyncPolicy if <code>std::launch::async</code> then the functor will attempt to be\n   * queued on the backing work queue of the Schedulable (if any).\n   * @param deferredPolicy if <code>std::launch::deferred</code>, <code>wait_for</code> and\n   * <code>wait_until</code> of the returned future will be allowed to invoke the functor, otherwise\n   * not.\n   *\n   * @return A future containing the result of the functor.\n   **/\n  template <typename F, typename Schedulable>\n  Future<detail::ResultOf<F, Future<Result>&&>> then(\n      F&& f,\n      Schedulable& sched,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred) {\n    Future<detail::ResultOf<F, Future<Result>&&>> retFuture;\n    retFuture.impl_ = this->template thenImpl<detail::ResultOf<F, Future<Result>&&>>(\n        std::forward<F>(f), sched, asyncPolicy, deferredPolicy);\n    return retFuture;\n  }\n  template <typename F>\n  Future<detail::ResultOf<F, Future<Result>&&>> then(F&& f) {\n    return then(std::forward<F>(f), globalThreadPool(), kNotAsync, std::launch::deferred);\n  }\n\n private:\n  template <typename T>\n  Future(T&& t, detail::ReadyTag) {\n    this->impl_ = detail::createValueFutureImplReady<Result>(std::forward<T>(t));\n  }\n\n  template <typename T>\n  friend Future<std::decay_t<T>> make_ready_future(T&& t);\n\n  template <typename R>\n  friend class Future;\n};\n\n/**\n * @copydoc Future\n */\ntemplate <typename Result>\nclass Future<Result&> : detail::FutureBase<Result&> {\n  using Base = detail::FutureBase<Result&>;\n\n public:\n  /** Default constructor. */\n  Future() noexcept : Base() {}\n  /** Move constructor. */\n  Future(Future&& f) noexcept : Base(std::move(f)) {}\n  /** @copydoc Future(Future&&) */\n  Future(Base&& f) noexcept : Base(std::move(f)) {}\n  /** Copy constructor. */\n  Future(const Future& f) noexcept : Base(f) {}\n  /** @copydoc Future(const Future&) */\n  Future(const Base& f) noexcept : Base(f) {}\n  /** Construct with callable and schedulable. @see Future<Result>::Future(F&&, Schedulable&,\n   * std::launch, std::launch) */\n  template <typename F, typename Schedulable>\n  Future(\n      F&& f,\n      Schedulable& schedulable,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred)\n      : Base(std::forward<F>(f), schedulable, asyncPolicy, deferredPolicy) {}\n  Future& operator=(Future&& f) noexcept {\n    Base::move(reinterpret_cast<Base&&>(f));\n    return *this;\n  }\n  Future& operator=(const Future& f) {\n    Base::copy(f);\n    return *this;\n  }\n  ~Future() = default;\n  using Base::is_ready;\n  using Base::valid;\n  using Base::wait;\n  using Base::wait_for;\n  using Base::wait_until;\n\n  Future share() {\n    return std::move(*this);\n  }\n\n  /**\n   * Get the result of the future functor.  This function blocks until the result is ready.\n   *\n   * @return Access to the underlying reference.\n   **/\n  Result& get() const {\n    wait();\n    return this->impl_->result();\n  }\n\n  template <typename F, typename Schedulable>\n  Future<detail::ResultOf<F, Future<Result&>&&>> then(\n      F&& f,\n      Schedulable& sched,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred) {\n    Future<detail::ResultOf<F, Future<Result&>&&>> retFuture;\n    retFuture.impl_ = this->template thenImpl<detail::ResultOf<F, Future<Result&>&&>>(\n        std::forward<F>(f), sched, asyncPolicy, deferredPolicy);\n    return retFuture;\n  }\n  template <typename F>\n  Future<detail::ResultOf<F, Future<Result&>&&>> then(F&& f) {\n    return then(std::forward<F>(f), globalThreadPool(), kNotAsync, std::launch::deferred);\n  }\n\n private:\n  template <typename T>\n  Future(std::reference_wrapper<T> t, detail::ReadyTag) {\n    this->impl_ = detail::createRefFutureImplReady<Result>(t);\n  }\n\n  template <typename X>\n  friend Future<X&> make_ready_future(std::reference_wrapper<X> x);\n\n  template <typename R>\n  friend class Future;\n};\n\n/**\n * @copydoc Future\n */\ntemplate <>\nclass Future<void> : detail::FutureBase<void> {\n  using Base = detail::FutureBase<void>;\n\n public:\n  /** Default constructor. */\n  Future() noexcept : Base() {}\n  /** Move constructor. */\n  Future(Future&& f) noexcept : Base(std::move(f)) {}\n  /** @copydoc Future(Future&&) */\n  Future(Base&& f) noexcept : Base(std::move(f)) {}\n  /** Copy constructor. */\n  Future(const Future& f) noexcept : Base(f) {}\n  /** @copydoc Future(const Future&) */\n  Future(const Base& f) noexcept : Base(f) {}\n  /** Construct with callable and schedulable. @see Future<Result>::Future(F&&, Schedulable&,\n   * std::launch, std::launch) */\n  template <typename F, typename Schedulable>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  Future(\n      F&& f,\n      Schedulable& schedulable,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred)\n      : Base(std::forward<F>(f), schedulable, asyncPolicy, deferredPolicy) {}\n  Future& operator=(Future&& f) noexcept {\n    Base::move(reinterpret_cast<Base&&>(f));\n    return *this;\n  }\n  Future& operator=(const Future& f) {\n    Base::copy(f);\n    return *this;\n  }\n  ~Future() = default;\n  using Base::is_ready;\n  using Base::valid;\n  using Base::wait;\n  using Base::wait_for;\n  using Base::wait_until;\n\n  Future share() {\n    return std::move(*this);\n  }\n\n  /**\n   * Block until the functor has been called.\n   **/\n  void get() const {\n    wait();\n    this->impl_->result();\n  }\n\n  template <typename F, typename Schedulable>\n  Future<detail::ResultOf<F, Future<void>&&>> then(\n      F&& f,\n      Schedulable& sched,\n      std::launch asyncPolicy = kNotAsync,\n      std::launch deferredPolicy = std::launch::deferred) {\n    Future<detail::ResultOf<F, Future<void>&&>> retFuture;\n    retFuture.impl_ = this->template thenImpl<detail::ResultOf<F, Future<void>&&>>(\n        std::forward<F>(f), sched, asyncPolicy, deferredPolicy);\n    return retFuture;\n  }\n  template <typename F>\n  Future<detail::ResultOf<F, Future<void>&&>> then(F&& f) {\n    return then(std::forward<F>(f), globalThreadPool(), kNotAsync, std::launch::deferred);\n  }\n\n private:\n  Future(detail::ReadyTag) {\n    impl_ = detail::createVoidFutureImplReady();\n  }\n\n  friend Future<void> make_ready_future();\n\n  template <typename R>\n  friend class Future;\n};\n\n// TODO(bbudge): Determine if we should\n// a. Expand launch policies, and logically inherit from std::launch and\n// b. Whether async should truly mean on a new thread.\n// For now we will treat std::launch::async such that we pass ForceQueuingTag\n\n/**\n * Invoke a functor through the global dispenso thread pool.\n *\n * @param policy The bitmask policy for when/how the functor can be invoked.\n * <code>std::launch::async</code> will result in the functor being forced onto a ThreadPool work\n * queue.  <code>std::launch::deferred</code> specifies that <code>Future::wait_for</code> and\n * <code>Future::wait_until</code> may invoke the functor.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(std::launch policy, F&& f, Args&&... args) {\n  return Future<detail::ResultOf<F, Args...>>(\n      std::bind(std::forward<F>(f), std::forward<Args>(args)...), globalThreadPool(), policy);\n}\n\n/**\n * Invoke a functor through the global dispenso thread pool.\n *\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(F&& f, Args&&... args) {\n  return ::dispenso::async(std::launch::deferred, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\n/**\n * Invoke a functor through the specified dispenso thread pool.\n *\n * @param pool The ThreadPool to run the Future.\n * @param policy The bitmask policy for when/how the functor can be invoked.\n * <code>std::launch::async</code> will result in the functor being forced onto a ThreadPool work\n * queue.  <code>std::launch::deferred</code> specifies that <code>Future::wait_for</code> and\n * <code>Future::wait_until</code> may invoke the functor.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>>\nasync(ThreadPool& pool, std::launch policy, F&& f, Args&&... args) {\n  return Future<detail::ResultOf<F, Args...>>(\n      std::bind(std::forward<F>(f), std::forward<Args>(args)...), pool, policy);\n}\n\n/**\n * Invoke a functor through the specified dispenso thread pool.\n *\n * @param pool The ThreadPool to run the Future.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(ThreadPool& pool, F&& f, Args&&... args) {\n  return ::dispenso::async(\n      pool, std::launch::deferred, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\n/**\n * Invoke a functor through the specified dispenso TaskSet.\n *\n * @param tasks The TaskSet to run the Future.\n * @param policy The bitmask policy for when/how the functor can be invoked.\n * <code>std::launch::async</code> will result in the functor being forced onto a ThreadPool work\n * queue.  <code>std::launch::deferred</code> specifies that <code>Future::wait_for</code> and\n * <code>Future::wait_until</code> may invoke the functor.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>>\nasync(TaskSet& tasks, std::launch policy, F&& f, Args&&... args) {\n  return Future<detail::ResultOf<F, Args...>>(\n      std::bind(std::forward<F>(f), std::forward<Args>(args)...), tasks, policy);\n}\n\n/**\n * Invoke a functor through the specified dispenso TaskSet.\n *\n * @param tasks The TaskSet to run the Future.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(TaskSet& tasks, F&& f, Args&&... args) {\n  return ::dispenso::async(\n      tasks, std::launch::deferred, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\n/**\n * Invoke a functor through the specified dispenso ConcurrentTaskSet.\n *\n * @param tasks The ConcurrentTaskSet to run the Future.\n * @param policy The bitmask policy for when/how the functor can be invoked.\n * <code>std::launch::async</code> will result in the functor being forced onto a ThreadPool work\n * queue.  <code>std::launch::deferred</code> specifies that <code>Future::wait_for</code> and\n * <code>Future::wait_until</code> may invoke the functor.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>>\nasync(ConcurrentTaskSet& tasks, std::launch policy, F&& f, Args&&... args) {\n  return Future<detail::ResultOf<F, Args...>>(\n      std::bind(std::forward<F>(f), std::forward<Args>(args)...), tasks, policy);\n}\n\n/**\n * Invoke a functor through the specified dispenso ConcurrentTaskSet.\n *\n * @param tasks The ConcurrentTaskSet to run the Future.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(ConcurrentTaskSet& tasks, F&& f, Args&&... args) {\n  return ::dispenso::async(\n      tasks, std::launch::deferred, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\n/**\n * Invoke a functor on a new thread.\n *\n * @param sched A NewThreadInvoker\n * @param policy The bitmask policy for when/how the functor can be invoked.\n * <code>std::launch::async</code> will result in the functor being forced onto a ThreadPool work\n * queue.  <code>std::launch::deferred</code> specifies that <code>Future::wait_for</code> and\n * <code>Future::wait_until</code> may invoke the functor.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>>\nasync(NewThreadInvoker sched, std::launch policy, F&& f, Args&&... args) {\n  return Future<detail::ResultOf<F, Args...>>(\n      std::bind(std::forward<F>(f), std::forward<Args>(args)...), sched, policy);\n}\n\n/**\n * Invoke a functor on a new thread.\n *\n * @param sched A NewThreadInvoker.\n * @param f The functor to be passed, or a function to be executed\n * @param args The remaining arguments that will be passed to <code>f</code>\n **/\ntemplate <class F, class... Args>\ninline Future<detail::ResultOf<F, Args...>> async(NewThreadInvoker sched, F&& f, Args&&... args) {\n  return ::dispenso::async(\n      sched, std::launch::deferred, std::forward<F>(f), std::forward<Args>(args)...);\n}\n\n/**\n * Make a <code>Future</code> in a ready state with the value passed into\n * <code>make_ready_future</code>\n *\n * @param t the value to use to create the returned future.\n **/\ntemplate <typename T>\ninline Future<std::decay_t<T>> make_ready_future(T&& t) {\n  return Future<std::decay_t<T>>(std::forward<T>(t), detail::ReadyTag());\n}\n\n/**\n * Make a <code>Future</code> in a ready state with the <code>reference_wrapper</code> passed into\n * <code>make_ready_future</code>\n *\n * @param x the wrapped reference to use to create the returned future.\n **/\ntemplate <typename X>\ninline Future<X&> make_ready_future(std::reference_wrapper<X> x) {\n  return Future<X&>(x, detail::ReadyTag());\n}\n\n/**\n * Make a <code>Future<void></code> in a ready state.\n *\n **/\ninline Future<void> make_ready_future() {\n  return Future<void>(detail::ReadyTag());\n}\n\n/**\n * Take a collection of futures, and return a future which will be ready when all input futures are\n * ready.\n *\n * @param first An iterator to the start of the future collection.\n * @param last An iterator to the end of the future collection.\n *\n * @return A Future containing a vector holding copies of the input Futures.  The returned Future\n * will be in ready state when all input Futures are ready.\n *\n **/\ntemplate <class InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>> when_all(\n    InputIt first,\n    InputIt last);\n\n/**\n * Take a specific set of futures, and return a future which will be ready when all input futures\n *are ready.\n *\n * @param futures A parameter pack of futures.\n *\n * @return A Future containing a tuple holding copies of the input Futures.  The returned Future\n * will be in ready state when all input Futures are ready.\n *\n **/\ntemplate <class... Futures>\nauto when_all(Futures&&... futures) -> Future<std::tuple<std::decay_t<Futures>...>>;\n\n/**\n * Take a collection of futures, and return a future which will be ready when all input futures are\n * ready.\n *\n * @param taskSet A task set to register with such that after this call,\n * <code>taskSet::wait()</code> implies that the resultant future <code>is_ready()</code>\n * @param first An iterator to the start of the future collection.\n * @param last An iterator to the end of the future collection.\n *\n * @return A Future containing a vector holding copies of the input Futures.  The returned Future\n * will be in ready state when all input Futures are ready.\n *\n **/\ntemplate <class InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>>\nwhen_all(TaskSet& taskSet, InputIt first, InputIt last);\n/** @overload */\ntemplate <class InputIt>\nFuture<std::vector<typename std::iterator_traits<InputIt>::value_type>>\nwhen_all(ConcurrentTaskSet& taskSet, InputIt first, InputIt last);\n\n/**\n * Take a specific set of futures, and return a future which will be ready when all input futures\n *are ready.\n *\n * @param taskSet A task set to register with such that after this call,\n * <code>taskSet::wait()</code> implies that the resultant future <code>is_ready()</code>\n * @param futures A parameter pack of futures.\n *\n * @return A Future containing a tuple holding copies of the input Futures.  The returned Future\n * will be in ready state when all input Futures are ready.\n *\n **/\ntemplate <class... Futures>\nauto when_all(TaskSet& taskSet, Futures&&... futures)\n    -> Future<std::tuple<std::decay_t<Futures>...>>;\n\n/** @overload */\ntemplate <class... Futures>\nauto when_all(ConcurrentTaskSet& taskSet, Futures&&... futures)\n    -> Future<std::tuple<std::decay_t<Futures>...>>;\n} // namespace dispenso\n\n#include <dispenso/detail/future_impl2.h>\n"
  },
  {
    "path": "dispenso/graph.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/graph.h>\n\n#include <iterator>\n#include <mutex>\n\nnamespace {\nconstexpr size_t kToDelete = std::numeric_limits<size_t>::max();\n\nvoid set_union(\n    std::vector<const dispenso::BiPropNode*>& s1,\n    const std::vector<const dispenso::BiPropNode*>& s2) {\n  std::vector<const dispenso::BiPropNode*> tmp(s1);\n  s1.clear();\n  std::set_union(tmp.cbegin(), tmp.cend(), s2.cbegin(), s2.cend(), std::back_inserter(s1));\n}\n\nvoid set_insert(std::vector<const dispenso::BiPropNode*>& s, const dispenso::BiPropNode* node) {\n  auto it = std::upper_bound(s.begin(), s.end(), node);\n  if (it == s.begin() || *(it - 1) != node) {\n    s.insert(it, node);\n  }\n}\n} // anonymous namespace\n\nnamespace dispenso {\n\nvoid BiPropNode::biPropDependsOnOneNode(BiPropNode& node) {\n  Node::dependsOnOneNode(node);\n  if (node.biPropSet_ == nullptr && biPropSet_ == nullptr) {\n    biPropSet_ = std::make_shared<std::vector<const BiPropNode*>>();\n    set_insert(*biPropSet_, this);\n    set_insert(*biPropSet_, &node);\n    node.biPropSet_ = biPropSet_;\n  } else if (node.biPropSet_ != nullptr && biPropSet_ != nullptr) {\n    set_union(*biPropSet_, *node.biPropSet_);\n    node.biPropSet_ = biPropSet_;\n  } else if (biPropSet_ == nullptr) {\n    biPropSet_ = node.biPropSet_;\n    set_insert(*biPropSet_, this);\n  } else {\n    node.biPropSet_ = biPropSet_;\n    set_insert(*biPropSet_, &node);\n  }\n}\n\ntemplate <class N>\nvoid SubgraphT<N>::clear() {\n  decrementDependentCounters();\n  const size_t numGraphPredecessors = markNodesWithPredicessors();\n  if (numGraphPredecessors != 0) {\n    removePredecessorDependencies(numGraphPredecessors);\n  }\n  destroyNodes();\n}\n\ntemplate <class N>\nvoid SubgraphT<N>::destroyNodes() {\n  for (NodeType* n : nodes_) {\n    n->~NodeType();\n  }\n  allocator_->clear();\n  nodes_.clear();\n}\n\ntemplate <class N>\nSubgraphT<N>::~SubgraphT() {\n  for (NodeType* n : nodes_) {\n    n->~NodeType();\n  }\n}\n\ntemplate <class N>\nvoid SubgraphT<N>::decrementDependentCounters() {\n  for (N* node : nodes_) {\n    for (Node* const dependent : node->dependents_) {\n      dependent->numPredecessors_--;\n    }\n    removeNodeFromBiPropSet(node);\n  }\n}\n\ntemplate <class N>\nsize_t SubgraphT<N>::markNodesWithPredicessors() {\n  size_t numGraphPredecessors = 0;\n  for (N* node : nodes_) {\n    if (node->numPredecessors_ != 0) {\n      numGraphPredecessors += node->numPredecessors_;\n      node->numPredecessors_ = kToDelete;\n    }\n  }\n  return numGraphPredecessors;\n}\n\ntemplate <class N>\nvoid SubgraphT<N>::removePredecessorDependencies(size_t numGraphPredecessors) {\n  for (SubgraphT<N>& subgraph : graph_->subgraphs_) {\n    if (&subgraph == this) {\n      continue;\n    }\n    for (N* node : subgraph.nodes_) {\n      auto& dependents = node->dependents_;\n      size_t num = dependents.size();\n      for (size_t i = 0; i < num;) {\n        if (dependents[i]->numPredecessors_ == kToDelete) {\n          dependents[i] = dependents[num - 1];\n          --num;\n          if (--numGraphPredecessors == 0) {\n            dependents.resize(num);\n            return;\n          }\n        } else {\n          i++;\n        }\n      }\n      dependents.resize(num);\n    }\n  }\n}\n\nnamespace {\nconstexpr size_t kMaxCache = 8;\n// Don't cache too-large allocators.  This way we will have at most 8*(2**16) = 512K outstanding\n// nodes worth of memory per node type.\n// TODO(bbudge): Make these caching values macro configurable for lightweight platforms.\nconstexpr size_t kMaxChunkCapacity = 1 << 16;\n\nusing AlignedNodePoolPtr =\n    std::unique_ptr<NoLockPoolAllocator, detail::AlignedFreeDeleter<NoLockPoolAllocator>>;\n\nstd::vector<AlignedNodePoolPtr> g_sgcache[2];\nstd::mutex g_sgcacheMtx;\n\ntemplate <class T>\nconstexpr size_t kCacheIndex = size_t{std::is_same<T, BiPropNode>::value};\n\n} // namespace\n\ntemplate <class N>\ntypename SubgraphT<N>::PoolPtr SubgraphT<N>::getAllocator() {\n  AlignedNodePoolPtr ptr;\n\n  auto& cache = g_sgcache[kCacheIndex<N>];\n\n  {\n    std::lock_guard<std::mutex> lk(g_sgcacheMtx);\n    if (cache.empty()) {\n      void* alloc =\n          detail::alignedMalloc(sizeof(NoLockPoolAllocator), alignof(NoLockPoolAllocator));\n      auto* pool = new (alloc)\n          NoLockPoolAllocator(sizeof(NodeType), 128 * sizeof(NodeType), ::malloc, ::free);\n      ptr.reset(pool);\n    } else {\n      ptr = std::move(cache.back());\n      ptr->clear();\n      cache.pop_back();\n    }\n  }\n  return PoolPtr(ptr.release(), releaseAllocator);\n}\n\ntemplate <class N>\nvoid SubgraphT<N>::releaseAllocator(NoLockPoolAllocator* ptr) {\n  if (!ptr) {\n    return;\n  }\n  if (ptr->totalChunkCapacity() < kMaxChunkCapacity) {\n    auto& cache = g_sgcache[kCacheIndex<N>];\n    {\n      std::lock_guard<std::mutex> lk(g_sgcacheMtx);\n      if (cache.size() < kMaxCache) {\n        cache.emplace_back(ptr);\n        return;\n      }\n    }\n  }\n  detail::AlignedFreeDeleter<NoLockPoolAllocator>()(ptr);\n}\n\ntemplate <class N>\nGraphT<N>::GraphT(GraphT<N>&& other) : subgraphs_(std::move(other.subgraphs_)) {\n  for (SubgraphT<N>& subgraph : subgraphs_) {\n    subgraph.graph_ = this;\n  }\n}\n\ntemplate <class N>\nGraphT<N>& GraphT<N>::operator=(GraphT&& other) noexcept {\n  subgraphs_ = std::move(other.subgraphs_);\n  for (SubgraphT<N>& subgraph : subgraphs_) {\n    subgraph.graph_ = this;\n  }\n  return *this;\n}\n\ntemplate <class N>\nSubgraphT<N>& GraphT<N>::addSubgraph() {\n  subgraphs_.push_back(SubgraphType(this));\n  return subgraphs_.back();\n}\n\ntemplate class DISPENSO_DLL_ACCESS SubgraphT<Node>;\ntemplate class DISPENSO_DLL_ACCESS SubgraphT<BiPropNode>;\ntemplate class DISPENSO_DLL_ACCESS GraphT<Node>;\ntemplate class DISPENSO_DLL_ACCESS GraphT<BiPropNode>;\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/graph.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file graph.h\n * @ingroup group_graph\n * A file providing task graph functionality for expressing complex task dependencies.\n **/\n\n#pragma once\n\n#include <atomic>\n#include <deque>\n#include <limits>\n#include <memory>\n#include <type_traits>\n#include <vector>\n\n#include <dispenso/once_function.h>\n#include <dispenso/platform.h>\n#include <dispenso/pool_allocator.h>\n#include <dispenso/small_buffer_allocator.h>\n#include <dispenso/small_vector.h>\n\n/**\n * @def DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE\n * @brief Number of dependent node pointers to store inline in each Node.\n *\n * Most graph nodes have few dependents (1-4 is common). This value controls\n * how many dependent pointers are stored inline before heap allocation.\n * Larger values reduce heap allocations but increase Node size.\n * Define before including graph.h to customize.\n **/\n#ifndef DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE\n#define DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE 4\n#endif\n\nstatic_assert(\n    DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE >= 1 && DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE <= 64,\n    \"DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE must be between 1 and 64\");\n\n/*\nTerminology\n--------------------------------------------------------------------------------\nThe Node depends on the predecessor. The dependent depends on the node.\n~~~\n┌─────────────┐     ┌──────┐     ┌───────────┐\n│ predecessor │ ──▶ │ node │ ──▶ │ dependent │\n└─────────────┘     └──────┘     └───────────┘\n~~~\n\nGraph construction\n--------------------------------------------------------------------------------\nThe Graph class can be used to created tasks with dependencies and execute it once.\nGraphs must not contain cycles.\nExample:\n~~~\n//\n//   ┌────────────┐     ┌───────────────┐     ┌───────────────────┐\n//   │ 0: r[0]+=1 │ ──▶ │ 1: r[1]=r[0]*2│ ──▶ │ 4: r[4]=r[1]+r[3] │\n//   └────────────┘     └───────────────┘     └───────────────────┘\n//                                              ▲\n//   ┌────────────┐     ┌───────────────┐       │\n//   │ 2: r[2]+=8 │ ──▶ │ 3: r[3]=r[2]/2│ ──────┘\n//   └────────────┘     └───────────────┘\n\nstd::array<float, 5> r;\n\ndispenso::Graph graph;\n\ndispenso::Node& N0 = graph.addNode([&]() { r[0] += 1; });\ndispenso::Node& N2 = graph.addNode([&]() { r[2] += 8; });\ndispenso::Node& N1 = graph.addNode([&]() { r[1] += r[0] * 2; });\ndispenso::Node& N3 = graph.addNode([&]() { r[3] += r[2] / 2; });\ndispenso::Node& N4 = graph.addNode([&]() { r[4] += r[1] + r[3]; });\n\nN4.dependsOn(N1, N3);\nN1.dependsOn(N0);\nN3.dependsOn(N2);\n\ndispenso::TaskSet taskSet(dispenso::globalThreadPool());\ndispenso::ParallelForExecutor parallelForExecutor;\nparallelForExecutor(taskSet, graph);\n~~~\n\nPartial revaluation\n--------------------------------------------------------------------------------\nIf graph is big or we need to recompute graph partially we can execute it again.\nAfter execution of the graph all nodes change their state from \"incomplete\" to\n\"completed\". If order to evaluate whole graph again we can use function `setAllNodesIncomplete`\nExample:\n~~~\nr = {0, 0, 0, 0, 0};\nsetAllNodesIncomplete(graph);\nparallelForExecutor(taskSet, graph);\n~~~\n\nThe graph can be recomputed partially if we have new input data for one or several nodes in the\ngraph. It order to do it we need to call `setIncomplete()` method for every node which we need to\nrecompute and after use functor `ForwardPropagator` to mark as \"incomplete\" all dependents.\n\nExample:\n~~~\nN1.setIncomplete();\nr[1] = r[4] = 0;\nForwardPropagator forwardPropagator;\nforwardPropagator(graph);\nevaluateGraph(graph);\n~~~\nIn this exaple only node 1 and 4 will be invoked.\n\n Subgraphs\n--------------------------------------------------------------------------------\nIt is possible to organize nodes into subgraphs and destroy and recreate if we have static and\ndynamic parts of the computation graph\nExample:\n~~~\n//\n// ∙----subgraph1---∙ ∙---subgraph2-------∙\n// ¦ ┌────────────┐ ¦ ¦ ┌───────────────┐ ¦   ┌───────────────────┐\n// ¦ │ 0: r[0]+=1 │ ──▶ │ 1: r[1]=r[0]*2│ ──▶ │ 4: r[4]=r[1]+r[3] │\n// ¦ └────────────┘ ¦ ¦ └───────────────┘ ¦   └───────────────────┘\n// ¦                ¦ ¦                   ¦     ▲\n// ¦ ┌────────────┐ ¦ ¦ ┌───────────────┐ ¦     │\n// ¦ │ 2: r[2]+=8 │ ──▶ │ 3: r[3]=r[2]/2│ ──────┘\n// ¦ └────────────┘ ¦ ¦ └───────────────┘ ¦\n// ∙----------------∙ ∙-------------------∙\nstd::array<float, 5> r;\ndispenso::Graph graph;\n\ndispenso::Subgraph& subgraph1 = graph.addSubgraph();\ndispenso::Subgraph& subgraph2 = graph.addSubgraph();\n\ndispenso::Node& N0 = subgraph1.addNode([&]() { r[0] += 1; });\ndispenso::Node& N2 = subgraph1.addNode([&]() { r[2] += 8; });\ndispenso::Node& N1 = subgraph2.addNode([&]() { r[1] += r[0] * 2; });\ndispenso::Node& N3 = subgraph2.addNode([&]() { r[3] += r[2] / 2; });\ndispenso::Node& N4 = graph.addNode([&]() { r[4] += r[1] + r[3]; });\n\nN4.dependsOn(N1, N3);\nN1.dependsOn(N0);\nN3.dependsOn(N2);\n\n// evaluate graph first time\nr = {0, 0, 0, 0, 0};\ndispenso::ConcurrentTaskSet concurrentTaskSet(dispenso::globalThreadPool());\ndispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\nconcurrentTaskSetExecutor(concurrentTaskSet, graph);\n\n// disconnect and destroy nodes of subgraph2\n// it invalidates node references/pointers of this subgraph\nsubgraph2.clear();\n\n// create another nodes\ndispenso::Node& newN1 = subgraph2.addNode([&]() { r[1] += r[0] * 20; });\ndispenso::Node& newN3 = subgraph2.addNode([&]() { r[3] += r[2] / 20; });\nnewN1.dependsOn(N0);\nnewN3.dependsOn(N2);\nN4.dependsOn(newN1, newN3);\n\n// and revaluae the graph\nsetAllNodesIncomplete(movedGraph);\nconcurrentTaskSetExecutor(concurrentTaskSet, graph);\n~~~\n\nBidirectional propagation dependency\n--------------------------------------------------------------------------------\nIn certain scenarios, nodes may alter the same memory. In such instances, it becomes necessary to\ncompute the predecessors of the node, even if they possess a \"completed\" state following state\npropagation. To facilitate this process automatically, we introduce the notion of a bidirectional\npropagation dependency (`BiProp`).\n\nExample:\n~~~\n//                     ┌─────────────────┐\n//                     │ 3: m3+=b*b      │\n//                     └─────────────────┘\n//                       ▲\n// ┌−-----------−−−−−−−−−│−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐\n// ╎ ┌───────────┐     ┌─────────────────┐     ┌────────────┐ ╎\n// ╎ │  0: b+=5  │ ──▷ │     1: b*=5     │ ──▷ │ 2: b/=m4   │ ╎\n// ╎ └───────────┘     └─────────────────┘     └────────────┘ ╎\n// └−−−-−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−▲−−−−−−−−−−−−┘\n//  Legend:                                      │\n//  ──▶ Normal dependency                      ┌────────────┐\n//  ──▷ Bidirectional propagation dependency   │ 4: m4+=2   │\n//  m4  variable modified only in node 4       └────────────┘\n\nfloat  b,  m3, m4\ndispenso::BiPropGraph g;\nstd::array<dispenso::BiPropNode*, 8> N;\n\ndispenso::BiPropNode& N0 = g.addNode([&]() { b += 5; });\ndispenso::BiPropNode& N1 = g.addNode([&]() { b *= 5; });\ndispenso::BiPropNode& N2 = g.addNode([&]() { b /= m4; });\ndispenso::BiPropNode& N3 = g.addNode([&]() { m3 += b*b; });\ndispenso::BiPropNode& N4 = g.addNode([&]() { m4 += 2; });\n\nN3.dependsOn(N1);\nN2.dependsOn(N4);\nN2.biPropDependsOn(N1);\nN1.biPropDependsOn(N0);\n\n// first execution\nb = m3 = m4 = 0.f;\ndispenso::ConcurrentTaskSet concurrentTaskSet(dispenso::globalThreadPool());\ndispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\nconcurrentTaskSetExecutor(concurrentTaskSet, g);\n\nN[4].setIncomplete();\n// if node 4 is incomplete after propagation node 2 become incomplete. Taking in account that node 2\n// bidirectionally depends on nodes 0 and 1 they will be marked as incomplete as well\nb =  m4 = 0.f;\nForwardPropagator forwardPropagator;\nforwardPropagator(g);\nconcurrentTaskSetExecutor(concurrentTaskSet, g);\n~~~\n\nPlease read tests from `graph_test.cpp` for more examples.\n*/\n\nnamespace detail {\nclass ExecutorBase;\n\ntemplate <typename F>\nvoid callFunctor(void* ptr) {\n  (*static_cast<F*>(ptr))();\n}\n\ntemplate <typename F>\nvoid destroyFunctor(void* ptr) {\n  static_cast<F*>(ptr)->~F();\n  constexpr size_t kFuncSize = static_cast<size_t>(dispenso::detail::nextPow2(sizeof(F)));\n  dispenso::deallocSmallBuffer<kFuncSize>(ptr);\n}\n\n} // namespace detail\n\nnamespace dispenso {\n/**\n * Class to store task with dependencies\n **/\nclass Node {\n public:\n  Node() = delete;\n  Node(const Node&) = delete;\n  Node& operator=(const Node&) = delete;\n  /** Move constructor. */\n  Node(Node&& other) noexcept\n      : numIncompletePredecessors_(other.numIncompletePredecessors_.load()),\n        numPredecessors_(other.numPredecessors_),\n        invoke_(other.invoke_),\n        destroy_(other.destroy_),\n        funcBuffer_(other.funcBuffer_),\n        dependents_(std::move(other.dependents_)) {\n    other.funcBuffer_ = nullptr;\n  }\n  ~Node() {\n    if (funcBuffer_) {\n      destroy_(funcBuffer_);\n    }\n  }\n  /**\n   * Make this node depends on nodes. This is not concurrency safe.\n   *\n   * @param nodes predecessors of the node\n   **/\n  template <typename... Ns>\n  inline void dependsOn(Ns&... nodes) {\n    ((void)std::initializer_list<int>{(dependsOnOneNode(nodes), 0)...});\n  }\n  /**\n   * Invoke the type-erased functor. Change competed state of the node to \"Incomplete\".\n   * Concurrency safe.\n   **/\n  inline void run() const {\n    invoke_(funcBuffer_);\n    numIncompletePredecessors_.store(kCompleted, std::memory_order_release);\n  }\n  /**\n   * apply an func to each dependent of the node\n   *\n   * @param func a functor with signature <code>void(const Node&)</code>\n   **/\n  template <class F>\n  inline void forEachDependent(F&& func) const {\n    for (const Node* dependent : dependents_) {\n      func(*dependent);\n    }\n  }\n  /**\n   * apply an func to each dependent of the node This is not concurrency safe.\n   *\n   * @param func a functor with signature <code>void(Node&)</code>\n   **/\n  template <class F>\n  inline void forEachDependent(F&& func) {\n    for (Node* dependent : dependents_) {\n      func(*dependent);\n    }\n  }\n  /**\n   * Return the number of nodes this node depends on. Concurrency safe.\n   **/\n  inline size_t numPredecessors() const {\n    return numPredecessors_;\n  }\n  /**\n   * Return true if node is completed.\n   * New node always incomplete. If node was invoked it become completed. this\n   * state can be changed by calling <code>setIncomplete()</code>\n   * Concurrency safe.\n   **/\n  inline bool isCompleted() const {\n    return numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted;\n  }\n  /**\n   * Mark node incomplete. (that allows reevaluate this node again).\n   * Concurrency safe. This methods should never be called concurrent to when\n   * the graph execution is happening\n   *\n   * @return true if state was changed.\n   **/\n  inline bool setIncomplete() const {\n    if (numIncompletePredecessors_.load(std::memory_order_relaxed) == kCompleted) {\n      numIncompletePredecessors_.store(0, std::memory_order_relaxed);\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Mark node completed.\n   * Concurrency safe. This methods should never be called concurrent to when\n   * the graph execution is happening\n   **/\n  inline void setCompleted() const {\n    numIncompletePredecessors_.store(kCompleted, std::memory_order_relaxed);\n  }\n\n protected:\n  /** Construct a Node with a functor. @param f The functor to execute when the node runs. */\n  template <class F, class X = std::enable_if_t<!std::is_base_of<Node, F>::value, void>>\n  Node(F&& f) : numIncompletePredecessors_(0) {\n    using FNoRef = typename std::remove_reference<F>::type;\n\n    constexpr size_t kFuncSize = static_cast<size_t>(detail::nextPow2(sizeof(FNoRef)));\n    funcBuffer_ = allocSmallBuffer<kFuncSize>();\n    new (funcBuffer_) FNoRef(std::forward<F>(f));\n    invoke_ = ::detail::callFunctor<FNoRef>;\n    destroy_ = ::detail::destroyFunctor<FNoRef>;\n  }\n\n  void dependsOnOneNode(Node& node) {\n    node.dependents_.emplace_back(this);\n    numPredecessors_++;\n  }\n\n  static constexpr size_t kCompleted = std::numeric_limits<size_t>::max();\n  mutable std::atomic<size_t> numIncompletePredecessors_;\n  size_t numPredecessors_ = 0;\n\n private:\n  using InvokerType = void (*)(void* ptr);\n\n  InvokerType invoke_;\n  InvokerType destroy_;\n  char* funcBuffer_;\n\n  SmallVector<Node*, DISPENSO_GRAPH_DEPENDENTS_INLINE_SIZE> dependents_; // nodes depend on this\n\n  template <class N>\n  friend class SubgraphT;\n  friend class ::detail::ExecutorBase;\n  template <typename G>\n  friend void setAllNodesIncomplete(const G& graph);\n};\n/**\n * Class to store task with dependencies. Support bidirectional propagation dependency between\n *nodes.\n **/\nclass BiPropNode : public Node {\n public:\n  BiPropNode() = delete;\n  BiPropNode(const BiPropNode&) = delete;\n  BiPropNode& operator=(const BiPropNode&) = delete;\n  /** Move constructor. */\n  BiPropNode(BiPropNode&& other) noexcept\n      : Node(std::move(other)), biPropSet_(std::move(other.biPropSet_)) {}\n  /**\n   * Make this node depends on nodes. Create bidirectional propagation dependency. This is not\n   *concurrency safe.\n   *\n   * @param nodes predecessors of the node\n   **/\n  template <class... Ns>\n  inline void biPropDependsOn(Ns&... nodes) {\n    ((void)std::initializer_list<int>{(biPropDependsOnOneNode(nodes), 0)...});\n  }\n  /**\n   * Return true if node belongs to the same propogation set. (That means both nodes after\n   * propogation become completed/incomplete together.)\n   *\n   * @param node to test\n   **/\n  inline bool isSameSet(const BiPropNode& node) const {\n    return biPropSet_ && biPropSet_ == node.biPropSet_;\n  }\n\n private:\n  template <class T, class X = std::enable_if_t<!std::is_base_of<BiPropNode, T>::value, void>>\n  BiPropNode(T&& f) : Node(std::forward<T>(f)) {}\n  inline void removeFromBiPropSet() {\n    if (biPropSet_ != nullptr) {\n      auto it = std::find(biPropSet_->begin(), biPropSet_->end(), this);\n      if (it != biPropSet_->end()) {\n        biPropSet_->erase(it);\n      }\n    }\n  }\n\n  DISPENSO_DLL_ACCESS void biPropDependsOnOneNode(BiPropNode& node);\n\n  std::shared_ptr<std::vector<const BiPropNode*>> biPropSet_;\n\n  template <class N>\n  friend class SubgraphT;\n  friend class ::detail::ExecutorBase;\n};\n\ntemplate <class N>\nclass GraphT;\n\n/**\n * A subgraph within a Graph, containing a collection of nodes that can be executed together.\n *\n * @tparam N The node type (Node or BiPropNode).\n */\ntemplate <class N>\nclass DISPENSO_DLL_ACCESS SubgraphT {\n public:\n  using NodeType = N;\n  SubgraphT() = delete;\n  SubgraphT(const SubgraphT<N>&) = delete;\n  SubgraphT<N>& operator=(const SubgraphT<N>&) = delete;\n  /** Move constructor. */\n  SubgraphT(SubgraphT<N>&& other) noexcept\n      : graph_(other.graph_),\n        nodes_(std::move(other.nodes_)),\n        allocator_(std::move(other.allocator_)) {}\n  ~SubgraphT();\n  /**\n   * Construct a <code>NodeType</code> with a valid functor. This is not concurrency safe.\n   *\n   * @param f A functor with signature void().\n   * @return reference to the created node.\n   **/\n  template <class T>\n  DISPENSO_REQUIRES(OnceCallableFunc<T>)\n  N& addNode(T&& f) {\n    nodes_.push_back(new (allocator_->alloc()) NodeType(std::forward<T>(f)));\n    return *nodes_.back();\n  }\n  /**\n   * Return number of nodes in subgraph. Concurrency safe.\n   **/\n  size_t numNodes() const {\n    return nodes_.size();\n  }\n  /**\n   * Reserve capacity for the specified number of nodes.\n   * This can improve performance when the number of nodes is known in advance\n   * by avoiding vector reallocations during addNode calls.\n   * This is not concurrency safe.\n   *\n   * @param n - number of nodes to reserve capacity for\n   **/\n  void reserve(size_t n) {\n    nodes_.reserve(n);\n  }\n  /**\n   * Return const reference to node with index. Concurrency safe.\n   *\n   * @param index - index of the node\n   **/\n  const N& node(size_t index) const {\n    return *nodes_[index];\n  }\n  /**\n   * Return reference to node with index. Concurrency safe.\n   *\n   * @param index - index of the node\n   **/\n  N& node(size_t index) {\n    return *nodes_[index];\n  }\n  /**\n   * apply an func to each node of the subgraph. Concurrency safe.\n   *\n   * @param func a functor with signature <code>void(const Node&)</code>\n   **/\n  template <class F>\n  inline void forEachNode(F&& func) const {\n    for (const N* node : nodes_) {\n      func(*node);\n    }\n  }\n  /**\n   * apply an func to each node of the subgraph. This is not concurrency safe.\n   * This methods should never be called concurrent to when the graph execution is happening\n   *\n   * @param func a functor with signature <code>void(Node&)</code>\n   **/\n  template <class F>\n  inline void forEachNode(F&& func) {\n    for (N* node : nodes_) {\n      func(*node);\n    }\n  }\n  /**\n   * Removes all dependency between nodes of this subgraph and other nodes, destroy this subgraph\n   * nodes. This is not concurrency safe.\n   **/\n  void clear();\n\n private:\n  using DeallocFunc = void (*)(NoLockPoolAllocator*);\n  using PoolPtr = std::unique_ptr<NoLockPoolAllocator, DeallocFunc>;\n\n  static constexpr size_t kNodeSizeP2 = static_cast<size_t>(detail::nextPow2(sizeof(NodeType)));\n\n  explicit SubgraphT(GraphT<N>* graph) : graph_(graph), nodes_(), allocator_(getAllocator()) {}\n\n  inline void removeNodeFromBiPropSet(Node* /* node */) {}\n  void removeNodeFromBiPropSet(BiPropNode* node) {\n    node->removeFromBiPropSet();\n  }\n  void decrementDependentCounters();\n  size_t markNodesWithPredicessors();\n  void removePredecessorDependencies(size_t numGraphPredecessors);\n\n  void destroyNodes();\n\n  static PoolPtr getAllocator();\n  static void releaseAllocator(NoLockPoolAllocator* ptr);\n\n  GraphT<N>* graph_;\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(push)\n#pragma warning(disable : 4251)\n#endif\n  std::vector<N*> nodes_;\n\n  PoolPtr allocator_;\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(pop)\n#endif\n\n  template <class T>\n  friend class GraphT;\n};\n\n/**\n * A directed acyclic graph (DAG) for expressing task dependencies.\n *\n * GraphT manages a collection of subgraphs, each containing nodes that represent work to be done.\n * Nodes can have dependencies on other nodes, and the graph executor ensures nodes run only after\n * their dependencies complete.\n *\n * @tparam N The node type (Node or BiPropNode).\n */\ntemplate <class N>\nclass DISPENSO_DLL_ACCESS GraphT {\n public:\n  using NodeType = N;\n  using SubgraphType = SubgraphT<N>;\n  GraphT(const GraphT<N>&) = delete;\n  GraphT& operator=(const GraphT<N>&) = delete;\n  /**\n   * Create empty graph.\n   **/\n  GraphT() {\n    subgraphs_.push_back(SubgraphType(this));\n  }\n  /**\n   * Move constructor\n   **/\n  GraphT(GraphT<N>&& other);\n  /**\n   * Move assignment operator\n   **/\n  GraphT<N>& operator=(GraphT&& other) noexcept;\n  /**\n   * Construct a <code>NodeType</code> with a valid functor. This node is created into subgraph 0.\n   * This is not concurrency safe.\n   *\n   * @param f A functor with signature void().\n   **/\n  template <class T>\n  DISPENSO_REQUIRES(OnceCallableFunc<T>)\n  N& addNode(T&& f) {\n    return subgraphs_[0].addNode(std::forward<T>(f));\n  }\n  /**\n   * Return number of nodes in subgraph 0. Concurrency safe.\n   **/\n  size_t numNodes() const {\n    return subgraphs_[0].numNodes();\n  }\n  /**\n   * Return const reference to node with index in subgraph 0. Concurrency safe.\n   *\n   * @param index - index of the node\n   **/\n  const N& node(size_t index) const {\n    return subgraphs_[0].node(index);\n  }\n  /**\n   * Return reference to node with index in subgraph 0. Concurrency safe.\n   *\n   * @param index - index of the node\n   **/\n  N& node(size_t index) {\n    return subgraphs_[0].node(index);\n  }\n  /**\n   * Create an empty subgraph. This is not concurrency safe.\n   **/\n  SubgraphT<N>& addSubgraph();\n  /**\n   * Return number of subgraphs in the graph including subgraph 0. Concurrency safe.\n   **/\n  size_t numSubgraphs() const {\n    return subgraphs_.size();\n  }\n  /**\n   * Return const reference to subgraph with index. Concurrency safe.\n   *\n   * @param index - index of the subgraph.\n   **/\n  const SubgraphT<N>& subgraph(size_t index) const {\n    return subgraphs_[index];\n  }\n  /**\n   * Return reference to subgraph with index. Concurrency safe.\n   *\n   * @param index - index of the subgraph.\n   **/\n  SubgraphT<N>& subgraph(size_t index) {\n    return subgraphs_[index];\n  }\n  /**\n   * apply an func to each subgraph in the graph. Concurrency safe.\n   *\n   * @param func a functor with signature <code>void(const SubgraphT<N>&)</code>\n   **/\n  template <class F>\n  inline void forEachSubgraph(F&& func) const {\n    for (const SubgraphT<N>& subgraph : subgraphs_) {\n      func(subgraph);\n    }\n  }\n  /**\n   * apply an func to each subgraph in the graph. Concurrency safe.\n   *\n   * @param func a functor with signature <code>void(SubgraphT<N>&)</code>\n   **/\n  template <class F>\n  inline void forEachSubgraph(F&& func) {\n    for (SubgraphT<N>& subgraph : subgraphs_) {\n      func(subgraph);\n    }\n  }\n  /**\n   * apply an func to each node in the graph including all nodes from all subgraphs. Concurrency\n   * safe.\n   *\n   * @param func a functor with signature <code>void(const Node&)</code>\n   **/\n  template <class F>\n  inline void forEachNode(F&& func) const {\n    for (const SubgraphT<N>& subgraph : subgraphs_) {\n      for (const N* node : subgraph.nodes_) {\n        func(*node);\n      }\n    }\n  }\n  /**\n   * apply an func to each node in the graph. Concurrency safe.\n   *\n   * @param func a functor with signature <code>void(const Node&)</code>\n   **/\n  template <class F>\n  inline void forEachNode(F&& func) {\n    for (SubgraphT<N>& subgraph : subgraphs_) {\n      for (N* node : subgraph.nodes_) {\n        func(*node);\n      }\n    }\n  }\n  /**\n   * Destroy all nodes and subgraphs. This is not concurrency safe.\n   **/\n  inline void clear() {\n    subgraphs_.clear();\n    subgraphs_.push_back(SubgraphType(this));\n  }\n  /**\n   * Destroy all nodes. Keeps subgraphs. This is not concurrency safe.\n   **/\n  inline void clearSubgraphs() {\n    for (SubgraphT<N>& subgraph : subgraphs_) {\n      subgraph.destroyNodes();\n    }\n  }\n\n private:\n  static constexpr size_t kSubgraphSizeP2 =\n      static_cast<size_t>(detail::nextPow2(sizeof(SubgraphType)));\n\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(push)\n#pragma warning(disable : 4251)\n#endif\n  std::deque<SubgraphT<N>> subgraphs_;\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(pop)\n#endif\n\n  template <class T>\n  friend class SubgraphT;\n};\n\n/** A DAG for task scheduling with simple dependency tracking. */\nusing Graph = GraphT<Node>;\n/** A DAG for task scheduling with bidirectional dependency propagation. */\nusing BiPropGraph = GraphT<BiPropNode>;\n\n/** A subgraph within a Graph. */\nusing Subgraph = SubgraphT<Node>;\n/** A subgraph within a BiPropGraph. */\nusing BiPropSubgraph = SubgraphT<BiPropNode>;\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/graph_executor.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/graph_executor.h>\n\nnamespace dispenso {\n\ntemplate <typename G>\nvoid SingleThreadExecutor::operator()(const G& graph) {\n  using NodeType = typename G::NodeType;\n  nodesToExecute_.clear();\n  nodesToExecuteNext_.clear();\n\n  // Count total nodes to estimate capacity needs\n  size_t nodeCount = 0;\n  graph.forEachNode([&](const NodeType& node) {\n    ++nodeCount;\n    if (hasNoIncompletePredecessors(node)) {\n      nodesToExecute_.emplace_back(&node);\n    }\n  });\n\n  // Reserve capacity to avoid reallocations during execution\n  // Use a fraction of total nodes as estimate for max wave size\n  size_t estimatedWaveSize = std::max(nodesToExecute_.size(), nodeCount / 4);\n  nodesToExecute_.reserve(estimatedWaveSize);\n  nodesToExecuteNext_.reserve(estimatedWaveSize);\n\n  while (!nodesToExecute_.empty()) {\n    for (const Node* n : nodesToExecute_) {\n      const NodeType* node = static_cast<const NodeType*>(n);\n      node->run();\n      node->forEachDependent([&](const Node& d) {\n        if (decNumIncompletePredecessors(\n                static_cast<const NodeType&>(d), std::memory_order_relaxed)) {\n          nodesToExecuteNext_.emplace_back(static_cast<const NodeType*>(&d));\n        }\n      });\n    }\n    nodesToExecute_.swap(nodesToExecuteNext_);\n    nodesToExecuteNext_.clear();\n  }\n}\n\ntemplate <typename TaskSetT, typename G>\nvoid ParallelForExecutor::operator()(TaskSetT& taskSet, const G& graph) {\n  using NodeType = typename G::NodeType;\n  nodesToExecute_.clear();\n  nodesToExecuteNext_.clear();\n\n  // Count total nodes to estimate capacity needs\n  size_t nodeCount = 0;\n  graph.forEachNode([&](const NodeType& node) {\n    ++nodeCount;\n    if (hasNoIncompletePredecessors(node)) {\n      nodesToExecute_.emplace_back(&node);\n    }\n  });\n\n  // Reserve capacity to avoid reallocations during execution\n  size_t estimatedWaveSize = std::max(nodesToExecute_.size(), nodeCount / 4);\n  nodesToExecute_.reserve(estimatedWaveSize);\n  nodesToExecuteNext_.reserve(estimatedWaveSize);\n\n  while (!nodesToExecute_.empty()) {\n    // Use stateful parallel_for: each thread collects ready nodes locally\n    dispenso::parallel_for(\n        taskSet,\n        threadStates_,\n        []() { return ThreadLocalCollector{}; },\n        size_t(0),\n        nodesToExecute_.size(),\n        [this](ThreadLocalCollector& collector, size_t i) {\n          const NodeType* node = static_cast<const NodeType*>(nodesToExecute_[i]);\n          node->run();\n\n          node->forEachDependent([&](const Node& d) {\n            // Relaxed ordering is safe here because the parallel_for wave barrier\n            // provides a happens-before relationship, and nodesToExecute_.swap()\n            // between waves ensures visibility of all side effects from prior waves.\n            if (decNumIncompletePredecessors(\n                    static_cast<const NodeType&>(d), std::memory_order_relaxed)) {\n              collector.readyNodes.push_back(static_cast<const NodeType*>(&d));\n            }\n          });\n        });\n\n    // Merge thread-local collections into next wave\n    for (auto& collector : threadStates_) {\n      if (!collector.readyNodes.empty()) {\n        nodesToExecuteNext_.insert(\n            nodesToExecuteNext_.end(), collector.readyNodes.begin(), collector.readyNodes.end());\n        collector.readyNodes.clear();\n      }\n    }\n\n    nodesToExecute_.swap(nodesToExecuteNext_);\n    nodesToExecuteNext_.clear();\n  }\n}\n\ntemplate <typename G>\nvoid ConcurrentTaskSetExecutor::operator()(\n    dispenso::ConcurrentTaskSet& tasks,\n    const G& graph,\n    bool wait) {\n  using NodeType = typename G::NodeType;\n  startNodes_.clear();\n\n  graph.forEachNode([&](const NodeType& node) {\n    if (hasNoIncompletePredecessors(node)) {\n      startNodes_.emplace_back(&node);\n    }\n  });\n\n  for (const Node* n : startNodes_) {\n    const NodeType* node = static_cast<const NodeType*>(n);\n    tasks.schedule([&tasks, node]() { evaluateNodeConcurrently(tasks, node); });\n  }\n  if (wait) {\n    tasks.wait();\n  }\n}\n\ntemplate <typename G>\nvoid setAllNodesIncomplete(const G& graph) {\n  using NodeType = typename G::NodeType;\n\n  graph.forEachNode([&](const NodeType& node) {\n    node.numIncompletePredecessors_.store(node.numPredecessors(), std::memory_order_relaxed);\n  });\n}\n\ntemplate <typename G>\nvoid ForwardPropagator::operator()(const G& graph) {\n  using NodeType = typename G::NodeType;\n\n  nodesToVisit_.clear();\n  nodesToVisitNext_.clear();\n  visited_.clear();\n  groups_.clear();\n\n  graph.forEachNode([&](const NodeType& node) {\n    if (!node.isCompleted()) {\n      nodesToVisit_.emplace_back(&node);\n      visited_.insert(&node);\n      appendGroup(static_cast<const NodeType*>(&node), groups_);\n    }\n  });\n\n  while (!nodesToVisit_.empty()) {\n    for (const Node* node : nodesToVisit_) {\n      node->forEachDependent([&](const Node& d) {\n        addIncompletePredecessor(d);\n        if (visited_.insert(static_cast<const NodeType*>(&d)).second) {\n          nodesToVisitNext_.emplace_back(static_cast<const NodeType*>(&d));\n          appendGroup(static_cast<const NodeType*>(&d), groups_);\n        }\n      });\n    }\n    nodesToVisit_.swap(nodesToVisitNext_);\n    nodesToVisitNext_.clear();\n  }\n\n  propagateIncompleteStateBidirectionally<NodeType>();\n}\n\ntemplate <>\nvoid ForwardPropagator::propagateIncompleteStateBidirectionally<Node>() {}\ntemplate <>\nvoid ForwardPropagator::propagateIncompleteStateBidirectionally<BiPropNode>() {\n  nodesToVisit_.clear();\n\n  for (const std::vector<const BiPropNode*>* group : groups_) {\n    for (const dispenso::BiPropNode* gnode : *group) {\n      if (gnode->setIncomplete()) {\n        nodesToVisit_.emplace_back(gnode);\n      }\n    }\n  }\n\n  for (const Node* node : nodesToVisit_) {\n    const BiPropNode* biPropNode = static_cast<const BiPropNode*>(node);\n    biPropNode->forEachDependent([](const Node& d) { ifIncompleteAddIncompletePredecessor(d); });\n  }\n}\n\ntemplate DISPENSO_DLL_ACCESS void SingleThreadExecutor::operator()<Graph>(const Graph&);\ntemplate DISPENSO_DLL_ACCESS void SingleThreadExecutor::operator()<BiPropGraph>(const BiPropGraph&);\n\ntemplate DISPENSO_DLL_ACCESS void ParallelForExecutor::operator()<TaskSet, Graph>(\n    TaskSet&,\n    const Graph&);\ntemplate DISPENSO_DLL_ACCESS void ParallelForExecutor::operator()<TaskSet, BiPropGraph>(\n    TaskSet&,\n    const BiPropGraph&);\ntemplate DISPENSO_DLL_ACCESS void ParallelForExecutor::operator()<ConcurrentTaskSet, Graph>(\n    ConcurrentTaskSet& tasks,\n    const Graph& graph);\ntemplate DISPENSO_DLL_ACCESS void ParallelForExecutor::operator()<ConcurrentTaskSet, BiPropGraph>(\n    ConcurrentTaskSet& tasks,\n    const BiPropGraph& graph);\n\ntemplate DISPENSO_DLL_ACCESS void ConcurrentTaskSetExecutor::operator()<Graph>(\n    dispenso::ConcurrentTaskSet& tasks,\n    const Graph& graph,\n    bool wait);\ntemplate DISPENSO_DLL_ACCESS void ConcurrentTaskSetExecutor::operator()<BiPropGraph>(\n    dispenso::ConcurrentTaskSet& tasks,\n    const BiPropGraph& graph,\n    bool wait);\n\ntemplate DISPENSO_DLL_ACCESS void setAllNodesIncomplete<Graph>(const Graph&);\ntemplate DISPENSO_DLL_ACCESS void setAllNodesIncomplete<BiPropGraph>(const BiPropGraph&);\ntemplate DISPENSO_DLL_ACCESS void ForwardPropagator::operator()<Graph>(const Graph&);\ntemplate DISPENSO_DLL_ACCESS void ForwardPropagator::operator()<BiPropGraph>(const BiPropGraph&);\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/graph_executor.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file graph_executor.h\n * @ingroup group_graph\n * A file providing executors for running task graphs.\n **/\n\n#pragma once\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/detail/graph_executor_impl.h>\n#include <dispenso/graph.h>\n#include <dispenso/parallel_for.h>\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n/**\n * Class to invoke <code>Graph</code> or <code>BiPropGraph</code> on current thread.\n **/\nclass SingleThreadExecutor : public ::detail::ExecutorBase {\n public:\n  /**\n   * Invoke the graph. This is not concurrency safe.\n   *\n   * @param graph graph to invoke\n   **/\n  template <typename G>\n  void operator()(const G& graph);\n\n private:\n  std::vector<const Node*> nodesToExecute_;\n  std::vector<const Node*> nodesToExecuteNext_;\n};\n/**\n * Class to invoke <code>Graph</code> or <code>BiPropGraph</code> using\n * <code>dispenso::parallel_for</code> for every layer of the graph.\n **/\nclass ParallelForExecutor : public ::detail::ExecutorBase {\n public:\n  /**\n   * Invoke the graph. This is not concurrency safe.\n   *\n   * @param taskSet taksSet to use with <code>parallel_for</code>.\n   * @param graph graph to invoke\n   **/\n  template <typename TaskSetT, typename G>\n  void operator()(TaskSetT& taskSet, const G& graph);\n\n private:\n  // Per-thread state for collecting ready nodes locally during parallel_for\n  struct ThreadLocalCollector {\n    std::vector<const Node*> readyNodes;\n  };\n\n  std::vector<const Node*> nodesToExecute_;\n  std::vector<const Node*> nodesToExecuteNext_;\n  std::vector<ThreadLocalCollector> threadStates_;\n};\n/**\n * Class to invoke <code>Graph</code> or <code>BiPropGraph</code> using\n * <code>dispenso::ConcurrentTaskSet</code>\n **/\nclass ConcurrentTaskSetExecutor : public ::detail::ExecutorBase {\n public:\n  /**\n   * Invoke the graph. This is not concurrency safe.\n   *\n   * @param tasks <code>ConcurrentTaskSet</code> to schedule tasks.\n   * @param graph graph to invoke\n   * @param wait if true run <code>tasks.wait()</code> at the end of the function\n   **/\n  template <typename G>\n  void operator()(dispenso::ConcurrentTaskSet& tasks, const G& graph, bool wait = true);\n\n private:\n  std::vector<const Node*> startNodes_;\n};\n\n/**\n * Class to propagate incomplete state recursively from nodes to dependents\n **/\nclass ForwardPropagator : public ::detail::ExecutorBase {\n public:\n  /**\n   * Propagate incomplete state recursively from nodes to dependents\n   * This is not concurrency safe.\n   **/\n  template <class G>\n  void operator()(const G& graph);\n\n private:\n  template <class N>\n  void propagateIncompleteStateBidirectionally();\n\n  std::vector<const Node*> nodesToVisit_;\n  std::vector<const Node*> nodesToVisitNext_;\n  std::unordered_set<const Node*> visited_;\n  std::unordered_set<const std::vector<const BiPropNode*>*> groups_;\n};\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/latch.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file latch.h\n * @ingroup group_sync\n * A file providing a Latch barrier type, which gives a way for threads to wait until all expected\n * threads have reached this point.  This is intended to match API and behavior of C++20 std::latch.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n#include <dispenso/detail/completion_event_impl.h>\n\nnamespace dispenso {\n\n/**\n * A class which can be used for barrier scenarios.  See e.g.\n * https://en.cppreference.com/w/cpp/thread/latch\n **/\nclass Latch {\n public:\n  /**\n   * Construct a latch with expected number of threads to wait on.\n   *\n   * @param threadGroupCount The number of threads in the group.\n   **/\n  explicit Latch(uint32_t threadGroupCount) noexcept : impl_(threadGroupCount) {}\n\n  /**\n   * Decrement the counter in a non-blocking manner.\n   **/\n  void count_down(uint32_t n = 1) noexcept {\n    if (impl_.intrusiveStatus().fetch_sub(n, std::memory_order_acq_rel) == 1) {\n      impl_.notify(0);\n    }\n  }\n\n  /**\n   * See if the count has been reduced to zero, indicating all necessary threads\n   * have synchronized.\n   *\n   * @note try_wait is a misnomer, as the function never blocks.  We kept the name to match C++20\n   * API.\n   * @return true only if the internal counter has reached zero.\n   **/\n  bool try_wait() const noexcept {\n    return impl_.intrusiveStatus().load(std::memory_order_acquire) == 0;\n  }\n\n  /**\n   * Wait for all threads to have synchronized.\n   **/\n  void wait() const noexcept {\n    impl_.wait(0);\n  }\n\n  /**\n   * Decrement the counter and wait\n   **/\n  void arrive_and_wait() noexcept {\n    if (impl_.intrusiveStatus().fetch_sub(1, std::memory_order_acq_rel) > 1) {\n      impl_.wait(0);\n    } else {\n      impl_.notify(0);\n    }\n  }\n\n private:\n  detail::CompletionEventImpl impl_;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/once_function.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file once_function.h\n * @ingroup group_core\n * A file providing OnceFunction, a class providing void() signature for closure to be called only\n * once.  It is built to be cheap to create and move.\n **/\n\n#pragma once\n\n#include <utility>\n\n#include <dispenso/detail/once_callable_impl.h>\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n#if DISPENSO_HAS_CONCEPTS\n/**\n * @concept OnceCallableFunc\n * @brief A callable suitable for wrapping in OnceFunction or scheduling as a task.\n *\n * The callable must be invocable with no arguments. The return value (if any) is discarded.\n * This is the fundamental requirement for functors passed to OnceFunction,\n * ThreadPool::schedule, TaskSet::schedule, and similar scheduling interfaces.\n **/\ntemplate <typename F>\nconcept OnceCallableFunc = std::invocable<F>;\n#endif // DISPENSO_HAS_CONCEPTS\n\nnamespace detail {\ntemplate <typename Result>\nclass FutureBase;\ntemplate <typename Result>\nclass FutureImplBase;\n} // namespace detail\n\n/**\n * A class fullfilling the void() signature, and operator() must be called exactly once for valid\n * <code>OnceFunction</code>s.  This class can be much more efficient than std::function for type\n * erasing functors without too much state (currently < ~250 bytes).\n * @note The wrapped type-erased functor in OnceFunction is *not* deleted upon destruction, but\n * rather when operator() is called.  It is the user's responsibility to ensure that operator() is\n * called.\n *\n **/\nclass OnceFunction {\n public:\n  /**\n   * Construct a <code>OnceFunction</code> with invalid state.\n   **/\n  OnceFunction()\n#if defined DISPENSO_DEBUG\n      : data_(nullptr),\n        invoke_(nullptr)\n#endif // DISPENSO_DEBUG\n  {\n  }\n\n  /**\n   * Construct a <code>OnceFunction</code> with a valid functor.\n   *\n   * @param f A functor with signature void().  Ideally this should be a concrete functor (e.g. from\n   * lambda), though it will work with e.g. std::function.  The downside in the latter case is extra\n   * overhead for double type erasure.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  OnceFunction(F&& f) {\n    auto callable = detail::createOnceCallable(std::forward<F>(f));\n    data_ = callable.data;\n    invoke_ = callable.invoke;\n  }\n\n  OnceFunction(const OnceFunction& other) = delete;\n\n  /** Move constructor. */\n  OnceFunction(OnceFunction&& other) noexcept : data_(other.data_), invoke_(other.invoke_) {\n#if defined DISPENSO_DEBUG\n    other.data_ = nullptr;\n    other.invoke_ = nullptr;\n#endif // DISPENSO_DEBUG\n  }\n\n  OnceFunction& operator=(OnceFunction&& other) noexcept {\n    data_ = other.data_;\n    invoke_ = other.invoke_;\n#if defined DISPENSO_DEBUG\n    if (&other != this) {\n      other.data_ = nullptr;\n      other.invoke_ = nullptr;\n    }\n#endif // DISPENSO_DEBUG\n    return *this;\n  }\n\n  /**\n   * Destroy the type-erased functor and release its resources without invoking it.\n   * Use this when a OnceFunction will not be called but its resources must still be freed.\n   * Like operator(), this must be called at most once, and the OnceFunction must not be used after.\n   **/\n  void cleanupNotRun() const {\n#if defined DISPENSO_DEBUG\n    assert(data_ != nullptr && \"Must not cleanup an invalid OnceFunction!\");\n    invoke_(data_, false);\n    data_ = nullptr;\n    invoke_ = nullptr;\n#else\n    invoke_(data_, false);\n#endif // DISPENSO_DEBUG\n  }\n\n  /**\n   * Invoke the type-erased functor.  This function must be called exactly once.  Fewer will result\n   * in a leak, while more will invoke on an invalid object.\n   **/\n  void operator()() const {\n#if defined DISPENSO_DEBUG\n    assert(data_ != nullptr && \"Must not use OnceFunction more than once!\");\n#endif // DISPENSO_DEBUG\n\n    invoke_(data_, true);\n\n#if defined DISPENSO_DEBUG\n    data_ = nullptr;\n    invoke_ = nullptr;\n#endif // DISPENSO_DEBUG\n  }\n\n private:\n  OnceFunction(detail::OnceCallable* func, bool) : data_(func), invoke_(&detail::runOnceCallable) {}\n\n  mutable void* data_;\n  void (*invoke_)(void*, bool);\n\n  template <typename Result>\n  friend class detail::FutureBase;\n  template <typename Result>\n  friend class detail::FutureImplBase;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/parallel_for.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file parallel_for.h\n * @ingroup group_parallel\n * Functions for performing parallel for loops.\n **/\n\n#pragma once\n\n#include <cmath>\n#include <limits>\n\n#include <dispenso/detail/can_invoke.h>\n#include <dispenso/detail/per_thread_info.h>\n#include <dispenso/small_buffer_allocator.h>\n#include <dispenso/task_set.h>\n\nnamespace dispenso {\n\n#if DISPENSO_HAS_CONCEPTS\n/**\n * @concept ParallelForRangeFunc\n * @brief A callable suitable for chunked parallel_for with (begin, end) signature.\n *\n * The callable must be invocable with two integer arguments representing the chunk range.\n **/\ntemplate <typename F, typename IntegerT>\nconcept ParallelForRangeFunc = std::invocable<F, IntegerT, IntegerT>;\n\n/**\n * @concept ParallelForIndexFunc\n * @brief A callable suitable for element-wise parallel_for with single index signature.\n *\n * The callable must be invocable with a single integer argument representing the element index.\n **/\ntemplate <typename F, typename IntegerT>\nconcept ParallelForIndexFunc = std::invocable<F, IntegerT>;\n\n/**\n * @concept ParallelForStateRangeFunc\n * @brief A callable suitable for stateful chunked parallel_for.\n *\n * The callable must be invocable with (State&, begin, end) arguments.\n **/\ntemplate <typename F, typename StateRef, typename IntegerT>\nconcept ParallelForStateRangeFunc = std::invocable<F, StateRef, IntegerT, IntegerT>;\n\n/**\n * @concept ParallelForStateIndexFunc\n * @brief A callable suitable for stateful element-wise parallel_for.\n *\n * The callable must be invocable with (State&, index) arguments.\n **/\ntemplate <typename F, typename StateRef, typename IntegerT>\nconcept ParallelForStateIndexFunc = std::invocable<F, StateRef, IntegerT>;\n#endif // DISPENSO_HAS_CONCEPTS\n\n/**\n * Chunking strategy.  Typically if the cost of each loop iteration is roughly constant, kStatic\n * load balancing is preferred.  Additionally, when making a non-waiting parallel_for call in\n * conjunction with other parallel_for calls or with other task submissions to a TaskSet, some\n * dynamic load balancing is automatically introduced, and selecting kStatic load balancing here can\n * be better.  If the workload per iteration deviates a lot from constant, and some ranges may be\n * much cheaper than others, select kAuto.\n **/\nenum class ParForChunking { kStatic, kAuto };\n\n/**\n * A set of options to control parallel_for\n **/\nstruct ParForOptions {\n  /**\n   * The maximum number of threads to use.  This can be used to limit the number of threads below\n   * the number associated with the TaskSet's thread pool to control the degree of concurrency.\n   * Setting maxThreads to zero or one will result in serial operation.\n   **/\n  uint32_t maxThreads = std::numeric_limits<int32_t>::max();\n  /**\n   * Specify whether the return of the parallel_for signifies the work is complete.  If the\n   * parallel_for is initiated without providing a TaskSet, the parallel_for will always wait.\n   *\n   * @note If wait is true, the calling thread will always participate in computation.  If this is\n   * not desired, pass wait as false, and wait manually outside of the parallel_for on the passed\n   * TaskSet.\n   **/\n  bool wait = true;\n\n  /**\n   * Specify whether default chunking should be static or auto (dynamic load balancing).  This is\n   * used when invoking the version of parallel_for that takes index parameters (vs a ChunkedRange).\n   **/\n  ParForChunking defaultChunking = ParForChunking::kStatic;\n\n  /**\n   * Specify a minimum number of items per chunk for static or auto dynamic load balancing.  Cheaper\n   * workloads should have a higher number of minWorkItems.  Will be ignored if an explicit chunk\n   * size is provided to ChunkedRange.\n   **/\n  uint32_t minItemsPerChunk = 1;\n\n  /**\n   * When set to false, and StateContainers are supplied to parallel_for, re-create container from\n   * scratch each call to parallel_for.  When true, reuse existing state as much as possible (only\n   * create new state if we require more than is already available in the container).\n   **/\n  bool reuseExistingState = false;\n};\n\n/**\n * A helper class for <code>parallel_for</code>.  It provides various configuration parameters to\n * describe how to break up work for parallel processing.  ChunkedRanges can be created with Auto\n * chunking, Static chunking, or specific chunking.  Auto chunking makes large chunks for better\n * cache utilization, but tries to make enough chunks to provide some dynamic load balancing. Static\n * chunking makes N chunks given N threads to run the loop on.  User-specified chunking can be\n * useful for ensuring e.g. that at least a multiple of SIMD width is provided per chunk.\n * <code>parallel_for</code> calls that don't accept a ChunkedRange will create a ChunkedRange\n * internally using Auto chunking.\n **/\ntemplate <typename IntegerT = ssize_t>\nstruct ChunkedRange {\n  // We need to utilize 64-bit integers to avoid overflow, e.g. passing -2**30, 2**30 as int32 will\n  // result in overflow unless we cast to 64-bit.  Note that if we have a range of e.g. -2**63+1 to\n  // 2**63-1, we cannot hold the result in an int64_t.  We could in a uint64_t, but it is quite\n  // tricky to make this work.  However, I do not expect ranges larger than can be held in int64_t\n  // since people want their computations to finish before the heat death of the sun (slight\n  // exaggeration).\n  using size_type = std::conditional_t<std::is_signed<IntegerT>::value, int64_t, uint64_t>;\n\n  struct Static {};\n  struct Auto {};\n  static constexpr IntegerT kStatic = std::numeric_limits<IntegerT>::max();\n\n  /**\n   * Create a ChunkedRange with specific chunk size\n   *\n   * @param s The start of the range.\n   * @param e The end of the range.\n   * @param c The chunk size.\n   **/\n  ChunkedRange(IntegerT s, IntegerT e, IntegerT c) : start(s), end(e), chunk(c) {}\n  /**\n   * Create a ChunkedRange with chunk size equal to total items divided by number of threads.\n   *\n   * @param s The start of the range.\n   * @param e The end of the range.\n   **/\n  ChunkedRange(IntegerT s, IntegerT e, Static) : ChunkedRange(s, e, kStatic) {}\n  /**\n   * Create a ChunkedRange with chunk size determined automatically to enable some dynamic load\n   * balancing.\n   *\n   * @param s The start of the range.\n   * @param e The end of the range.\n   **/\n  ChunkedRange(IntegerT s, IntegerT e, Auto) : ChunkedRange(s, e, 0) {}\n\n  bool isStatic() const {\n    return chunk == kStatic;\n  }\n\n  bool isAuto() const {\n    return chunk == 0;\n  }\n\n  bool empty() const {\n    return end <= start;\n  }\n\n  size_type size() const {\n    return static_cast<size_type>(end) - start;\n  }\n\n  template <typename OtherInt>\n  std::tuple<size_type, size_type>\n  calcChunkSize(OtherInt numLaunched, bool oneOnCaller, size_type minChunkSize) const {\n    size_type workingThreads = static_cast<size_type>(numLaunched) + size_type{oneOnCaller};\n    assert(workingThreads > 0);\n\n    if (!chunk) {\n      size_type dynFactor = std::min<size_type>(16, size() / workingThreads);\n      size_type chunkSize;\n      do {\n        size_type roughChunks = dynFactor * workingThreads;\n        chunkSize = (size() + roughChunks - 1) / roughChunks;\n        --dynFactor;\n      } while (chunkSize < minChunkSize);\n      return {chunkSize, (size() + chunkSize - 1) / chunkSize};\n    } else if (chunk == kStatic) {\n      // This should never be called.  The static distribution versions of the parallel_for\n      // functions should be invoked instead.\n      std::abort();\n    }\n    return {chunk, (size() + chunk - 1) / chunk};\n  }\n\n  IntegerT start;\n  IntegerT end;\n  IntegerT chunk;\n};\n\n/**\n * Create a ChunkedRange with specified chunking strategy.\n *\n * @param start The start of the range.\n * @param end The end of the range.\n * @param chunking The strategy to use for chunking.\n **/\ntemplate <typename IntegerA, typename IntegerB>\ninline ChunkedRange<std::common_type_t<IntegerA, IntegerB>>\nmakeChunkedRange(IntegerA start, IntegerB end, ParForChunking chunking = ParForChunking::kStatic) {\n  using IntegerT = std::common_type_t<IntegerA, IntegerB>;\n  return (chunking == ParForChunking::kStatic)\n      ? ChunkedRange<IntegerT>(start, end, typename ChunkedRange<IntegerT>::Static())\n      : ChunkedRange<IntegerT>(start, end, typename ChunkedRange<IntegerT>::Auto());\n}\n\n/**\n * Create a ChunkedRange with specific chunk size\n *\n * @param start The start of the range.\n * @param end The end of the range.\n * @param chunkSize The chunk size.\n **/\ntemplate <typename IntegerA, typename IntegerB, typename IntegerC>\ninline ChunkedRange<std::common_type_t<IntegerA, IntegerB>>\nmakeChunkedRange(IntegerA start, IntegerB end, IntegerC chunkSize) {\n  return ChunkedRange<std::common_type_t<IntegerA, IntegerB>>(start, end, chunkSize);\n}\n\nnamespace detail {\n\nstruct NoOpIter {\n  using difference_type = std::ptrdiff_t;\n  using value_type = int;\n  using pointer = int*;\n  using reference = int&;\n  using iterator_category = std::random_access_iterator_tag;\n\n  int& operator*() const {\n    static DISPENSO_THREAD_LOCAL int dummy = 0;\n    return dummy;\n  }\n  NoOpIter& operator++() {\n    return *this;\n  }\n  NoOpIter operator++(int) {\n    return *this;\n  }\n  NoOpIter& operator--() {\n    return *this;\n  }\n  NoOpIter operator--(int) {\n    return *this;\n  }\n  NoOpIter& operator+=(difference_type) {\n    return *this;\n  }\n  NoOpIter& operator-=(difference_type) {\n    return *this;\n  }\n  NoOpIter operator+(difference_type) const {\n    return *this;\n  }\n  NoOpIter operator-(difference_type) const {\n    return *this;\n  }\n  difference_type operator-(const NoOpIter&) const {\n    return 0;\n  }\n  bool operator==(const NoOpIter&) const {\n    return true;\n  }\n  bool operator!=(const NoOpIter&) const {\n    return false;\n  }\n  bool operator<(const NoOpIter&) const {\n    return false;\n  }\n  int& operator[](difference_type) const {\n    static DISPENSO_THREAD_LOCAL int dummy = 0;\n    return dummy;\n  }\n};\n\nstruct NoOpContainer {\n  size_t size() const {\n    return 0;\n  }\n\n  bool empty() const {\n    return true;\n  }\n\n  void clear() {}\n\n  NoOpIter begin() {\n    return {};\n  }\n\n  void emplace_back(int) {}\n\n  int& front() {\n    static int i;\n    return i;\n  }\n};\n\nstruct NoOpStateGen {\n  int operator()() const {\n    return 0;\n  }\n};\n\n/**\n * Initialize states container with enough entries for the given thread count.\n * Respects reuseExistingState: when true, only adds entries if the container\n * doesn't already have enough.\n */\ntemplate <typename StateContainer, typename StateGen>\nvoid initStates(\n    StateContainer& states,\n    const StateGen& defaultState,\n    size_t numNeeded,\n    bool reuseExistingState) {\n  if (!reuseExistingState) {\n    states.clear();\n  }\n  for (size_t i = states.size(); i < numNeeded; ++i) {\n    states.emplace_back(defaultState());\n  }\n}\n\ntemplate <\n    typename TaskSetT,\n    typename IntegerT,\n    typename F,\n    typename StateContainer,\n    typename StateGen>\nvoid parallel_for_staticImpl(\n    TaskSetT& taskSet,\n    StateContainer& states,\n    const StateGen& defaultState,\n    const ChunkedRange<IntegerT>& range,\n    F&& f,\n    ssize_t maxThreads,\n    bool wait,\n    bool reuseExistingState) {\n  using size_type = typename ChunkedRange<IntegerT>::size_type;\n\n  size_type numThreads = std::min<size_type>(taskSet.numPoolThreads() + wait, maxThreads);\n  // Reduce threads used if they exceed work to be done.\n  numThreads = std::min(numThreads, range.size());\n\n  detail::initStates(states, defaultState, static_cast<size_t>(numThreads), reuseExistingState);\n\n  auto chunking =\n      detail::staticChunkSize(static_cast<ssize_t>(range.size()), static_cast<ssize_t>(numThreads));\n  IntegerT chunkSize = static_cast<IntegerT>(chunking.ceilChunkSize);\n\n  bool perfectlyChunked = static_cast<size_type>(chunking.transitionTaskIndex) == numThreads;\n\n  // Number of tasks to schedule (all but the last one if wait is true)\n  size_type numToSchedule = wait ? numThreads - 1 : numThreads;\n\n  if (numToSchedule > 0) {\n    // Precompute range boundaries for the generator\n    // First loop: indices [0, transitionTaskIndex) use ceilChunkSize\n    // Second loop: indices [transitionTaskIndex, numToSchedule) use ceilChunkSize - 1\n    size_type transitionIdx = perfectlyChunked ? numToSchedule : chunking.transitionTaskIndex;\n    IntegerT smallChunkSize = static_cast<IntegerT>(chunkSize - !perfectlyChunked);\n\n    taskSet.scheduleBulk(\n        static_cast<size_t>(numToSchedule),\n        [&, chunkSize, smallChunkSize, transitionIdx](size_t idx) {\n          // Calculate start position for this chunk\n          IntegerT start;\n          IntegerT thisChunkSize;\n          if (static_cast<size_type>(idx) < transitionIdx) {\n            IntegerT i = static_cast<IntegerT>(idx);\n            start = static_cast<IntegerT>(range.start + static_cast<IntegerT>(i * chunkSize));\n            thisChunkSize = chunkSize;\n          } else {\n            // After transition, chunks are smaller by 1\n            IntegerT ti = static_cast<IntegerT>(transitionIdx);\n            IntegerT ri = static_cast<IntegerT>(idx - transitionIdx);\n            start = static_cast<IntegerT>(\n                range.start + static_cast<IntegerT>(ti * chunkSize) +\n                static_cast<IntegerT>(ri * smallChunkSize));\n            thisChunkSize = smallChunkSize;\n          }\n          IntegerT end = static_cast<IntegerT>(start + thisChunkSize);\n\n          auto stateIt = states.begin();\n          std::advance(stateIt, static_cast<ptrdiff_t>(idx));\n\n          return [it = stateIt, start, end, f]() {\n            auto recurseInfo = detail::PerPoolPerThreadInfo::parForRecurse();\n            f(*it, start, end);\n          };\n        });\n  }\n\n  if (wait) {\n    // Execute the last chunk on the calling thread\n    auto stateIt = states.begin();\n    std::advance(stateIt, static_cast<ptrdiff_t>(numThreads - 1));\n    // Calculate start of last chunk\n    size_type transitionIdx = perfectlyChunked ? numThreads - 1 : chunking.transitionTaskIndex;\n    IntegerT smallChunkSize = static_cast<IntegerT>(chunkSize - !perfectlyChunked);\n    IntegerT lastStart;\n    if (numThreads - 1 < transitionIdx) {\n      IntegerT i = static_cast<IntegerT>(numThreads - 1);\n      lastStart = static_cast<IntegerT>(range.start + static_cast<IntegerT>(i * chunkSize));\n    } else {\n      IntegerT ti = static_cast<IntegerT>(transitionIdx);\n      IntegerT ri = static_cast<IntegerT>(numThreads - 1 - transitionIdx);\n      lastStart = static_cast<IntegerT>(\n          range.start + static_cast<IntegerT>(ti * chunkSize) +\n          static_cast<IntegerT>(ri * smallChunkSize));\n    }\n    f(*stateIt, lastStart, range.end);\n    taskSet.wait();\n  }\n}\n\ntemplate <typename IntegerT>\nstruct ChunkSizingResult {\n  typename ChunkedRange<IntegerT>::size_type maxThreads;\n  bool isStatic;\n};\n\n/**\n * Adjust the thread count and static/dynamic scheduling decision based on work size.\n *\n * The goal is to avoid oversubscription and ensure each thread gets enough work:\n *\n * 1. Cap maxThreads to available pool threads (plus calling thread if waiting).\n * 2. If minItemsPerChunk > 1, reduce thread count so each thread gets at least\n *    that many items. If even after reduction the chunks are too small, fall back\n *    to static scheduling (which distributes items evenly without atomic contention).\n * 3. If minItemsPerChunk == 1 and the range is smaller than the thread count,\n *    fall back to static scheduling (auto mode) or cap threads (explicit dynamic).\n */\ntemplate <typename IntegerT>\nChunkSizingResult<IntegerT> adjustChunkSizing(\n    const ChunkedRange<IntegerT>& range,\n    typename ChunkedRange<IntegerT>::size_type maxThreads,\n    bool isStatic,\n    uint32_t minItemsPerChunk,\n    typename ChunkedRange<IntegerT>::size_type poolThreads,\n    bool wait) {\n  using size_type = typename ChunkedRange<IntegerT>::size_type;\n\n  // Step 1: never use more threads than the pool actually has\n  maxThreads = std::min<size_type>(maxThreads, poolThreads + wait);\n\n  if (minItemsPerChunk > 1) {\n    // Step 2a: reduce threads so each gets at least minItemsPerChunk items\n    size_type maxWorkers = range.size() / minItemsPerChunk;\n    if (maxWorkers < maxThreads) {\n      maxThreads = maxWorkers;\n    }\n    // Step 2b: if dynamic chunks would still be too small, use static scheduling\n    if (maxThreads > 0 && range.size() / (maxThreads + wait) < minItemsPerChunk && range.isAuto()) {\n      isStatic = true;\n    }\n  } else if (range.size() <= poolThreads + wait) {\n    // Step 3: fewer items than threads — static is better (no atomic overhead)\n    if (range.isAuto()) {\n      isStatic = true;\n    } else if (!range.isStatic()) {\n      maxThreads = range.size() - wait;\n    }\n  }\n\n  return {maxThreads, isStatic};\n}\n\n/**\n * Dynamic (work-stealing) parallel_for implementation.\n *\n * Workers atomically claim chunks from a shared index and process them.\n * The ExitAction callback is invoked when a worker finds no more chunks;\n * this allows the no-wait path to deallocate a heap-allocated index when\n * the last worker exits, while the wait path passes a no-op.\n *\n * When wait is true, the calling thread participates as an additional worker\n * and blocks until all tasks complete.\n */\ntemplate <\n    typename TaskSetT,\n    typename IntegerT,\n    typename F,\n    typename StateContainer,\n    typename IndexRef,\n    typename ExitAction>\nvoid parallel_for_dynamicImpl(\n    TaskSetT& taskSet,\n    StateContainer& states,\n    IntegerT start,\n    IntegerT end,\n    F&& f,\n    size_t numToLaunch,\n    typename ChunkedRange<IntegerT>::size_type chunkSize,\n    typename ChunkedRange<IntegerT>::size_type numChunks,\n    IndexRef& index,\n    ExitAction exitAction,\n    bool wait) {\n  auto worker = [start, end, &index, f, chunkSize, numChunks, exitAction](auto& s) {\n    auto recurseInfo = detail::PerPoolPerThreadInfo::parForRecurse();\n    while (true) {\n      auto cur = index.fetch_add(1, std::memory_order_relaxed);\n      if (cur >= numChunks) {\n        exitAction(cur);\n        break;\n      }\n      auto sidx = static_cast<IntegerT>(start + cur * chunkSize);\n      if (cur + 1 == numChunks) {\n        f(s, sidx, end);\n      } else {\n        f(s, sidx, static_cast<IntegerT>(sidx + chunkSize));\n      }\n    }\n  };\n\n  taskSet.scheduleBulk(static_cast<size_t>(numToLaunch), [&states, &worker](size_t i) {\n    auto it = states.begin();\n    std::advance(it, static_cast<ptrdiff_t>(i));\n    return [&s = *it, worker]() { worker(s); };\n  });\n\n  if (wait) {\n    auto it = states.begin();\n    std::advance(it, static_cast<ptrdiff_t>(numToLaunch));\n    worker(*it);\n    taskSet.wait();\n  }\n}\n\n} // namespace detail\n\n/**\n * Execute loop over the range in parallel.\n *\n * @param taskSet The task set to schedule the loop on.\n * @param states A container of <code>State</code> (actual type of State TBD by user).  The\n * container will be resized to hold a <code>State</code> object per executing thread.  Container\n * must provide emplace_back() and must be forward-iterable.  Examples include std::vector,\n * std::deque, and std::list.  These are the states passed into <code>f</code>, and states must\n * remain a valid object until work is completed.\n * @param defaultState A functor with signature State().  It will be called to initialize the\n * objects for <code>states</code>.\n * @param range The range defining the loop extents as well as chunking strategy.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(State &s, size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.\n **/\ntemplate <\n    typename TaskSetT,\n    typename IntegerT,\n    typename F,\n    typename StateContainer,\n    typename StateGen>\nvoid parallel_for(\n    TaskSetT& taskSet,\n    StateContainer& states,\n    const StateGen& defaultState,\n    const ChunkedRange<IntegerT>& range,\n    F&& f,\n    ParForOptions options = {}) {\n  if (range.empty()) {\n    if (options.wait) {\n      taskSet.wait();\n    }\n    return;\n  }\n\n  using size_type = typename ChunkedRange<IntegerT>::size_type;\n\n  uint32_t minItemsPerChunk = std::max<uint32_t>(1, options.minItemsPerChunk);\n  size_type maxThreads = std::max<int32_t>(options.maxThreads, 1);\n  bool isStatic = range.isStatic();\n\n  const size_type N = taskSet.numPoolThreads();\n  if (N == 0 || !options.maxThreads || range.size() <= minItemsPerChunk ||\n      detail::PerPoolPerThreadInfo::isParForRecursive(&taskSet.pool())) {\n    detail::initStates(states, defaultState, 1, options.reuseExistingState);\n    f(*states.begin(), range.start, range.end);\n    if (options.wait) {\n      taskSet.wait();\n    }\n    return;\n  }\n\n  auto chunkSizing =\n      detail::adjustChunkSizing(range, maxThreads, isStatic, minItemsPerChunk, N, options.wait);\n  maxThreads = chunkSizing.maxThreads;\n  isStatic = chunkSizing.isStatic;\n\n  // If adjustment reduced threads below 2, run inline — not worth parallelizing.\n  if (maxThreads < 2) {\n    detail::initStates(states, defaultState, 1, options.reuseExistingState);\n    f(*states.begin(), range.start, range.end);\n    if (options.wait) {\n      taskSet.wait();\n    }\n    return;\n  }\n\n  if (isStatic) {\n    detail::parallel_for_staticImpl(\n        taskSet,\n        states,\n        defaultState,\n        range,\n        std::forward<F>(f),\n        static_cast<ssize_t>(maxThreads),\n        options.wait,\n        options.reuseExistingState);\n    return;\n  }\n\n  const size_type numToLaunch = std::min<size_type>(maxThreads - options.wait, N);\n\n  detail::initStates(\n      states,\n      defaultState,\n      static_cast<size_t>(numToLaunch + options.wait),\n      options.reuseExistingState);\n\n  if (numToLaunch == 1 && !options.wait) {\n    taskSet.schedule(\n        [&s = states.front(), range, f = std::move(f)]() { f(s, range.start, range.end); });\n    return;\n  }\n\n  auto chunkInfo = range.calcChunkSize(numToLaunch, options.wait, minItemsPerChunk);\n  auto chunkSize = std::get<0>(chunkInfo);\n  auto numChunks = std::get<1>(chunkInfo);\n\n  if (options.wait) {\n    alignas(kCacheLineSize) std::atomic<decltype(numChunks)> index(0);\n    detail::parallel_for_dynamicImpl(\n        taskSet,\n        states,\n        range.start,\n        range.end,\n        std::forward<F>(f),\n        static_cast<size_t>(numToLaunch),\n        chunkSize,\n        numChunks,\n        index,\n        [](auto) {},\n        options.wait);\n  } else {\n    using SizeType = decltype(numChunks);\n    struct ChunkIndex {\n      std::atomic<SizeType> index;\n    };\n    static_assert(sizeof(ChunkIndex) <= kCacheLineSize, \"ChunkIndex must fit in one cache line\");\n    char* mem = allocSmallBuffer<kCacheLineSize>();\n    auto* ci = new (mem) ChunkIndex{{0}};\n    SizeType lastExit = numChunks + static_cast<SizeType>(numToLaunch) - 1;\n    detail::parallel_for_dynamicImpl(\n        taskSet,\n        states,\n        range.start,\n        range.end,\n        std::forward<F>(f),\n        static_cast<size_t>(numToLaunch),\n        chunkSize,\n        numChunks,\n        ci->index,\n        [ci, lastExit](auto cur) {\n          if (cur == lastExit) {\n            deallocSmallBuffer<kCacheLineSize>(ci);\n          }\n        },\n        options.wait);\n  }\n}\n\n/**\n * Execute loop over the range in parallel.\n *\n * @param taskSet The task set to schedule the loop on.\n * @param range The range defining the loop extents as well as chunking strategy.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.\n **/\ntemplate <typename TaskSetT, typename IntegerT, typename F>\nDISPENSO_REQUIRES(ParallelForRangeFunc<F, IntegerT>)\nvoid parallel_for(\n    TaskSetT& taskSet,\n    const ChunkedRange<IntegerT>& range,\n    F&& f,\n    ParForOptions options = {}) {\n  detail::NoOpContainer container;\n  parallel_for(\n      taskSet,\n      container,\n      detail::NoOpStateGen(),\n      range,\n      [f = std::move(f)](int /*noop*/, auto i, auto j) { f(i, j); },\n      options);\n}\n\n/**\n * Execute loop over the range in parallel on the global thread pool, and wait until complete.\n *\n * @param range The range defining the loop extents as well as chunking strategy.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.  <code>options.wait</code> will always be reset\n *to true.\n **/\ntemplate <typename IntegerT, typename F>\nDISPENSO_REQUIRES(ParallelForRangeFunc<F, IntegerT>)\nvoid parallel_for(const ChunkedRange<IntegerT>& range, F&& f, ParForOptions options = {}) {\n  TaskSet taskSet(globalThreadPool());\n  options.wait = true;\n  parallel_for(taskSet, range, std::forward<F>(f), options);\n}\n\n/**\n * Execute loop over the range in parallel on the global thread pool and block until loop\n *completion.\n *\n * @param states A container of <code>State</code> (actual type of State TBD by user).  The\n * container will be resized to hold a <code>State</code> object per executing thread.  Container\n * must provide emplace_back() and must be forward-iterable.  Examples include std::vector,\n * std::deque, and std::list.  These are the states passed into <code>f</code>, and states must\n * remain a valid object until work is completed.\n * @param defaultState A functor with signature State().  It will be called to initialize the\n * objects for <code>states</code>.\n * @param range The range defining the loop extents as well as chunking strategy.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(State &s, size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.  <code>options.wait</code> will always be reset\n *to true.\n **/\ntemplate <typename F, typename IntegerT, typename StateContainer, typename StateGen>\nvoid parallel_for(\n    StateContainer& states,\n    const StateGen& defaultState,\n    const ChunkedRange<IntegerT>& range,\n    F&& f,\n    ParForOptions options = {}) {\n  TaskSet taskSet(globalThreadPool());\n  options.wait = true;\n  parallel_for(taskSet, states, defaultState, range, std::forward<F>(f), options);\n}\n\n/**\n * Execute loop over the range in parallel.\n *\n * @param taskSet The task set to schedule the loop on.\n * @param start The start of the loop extents.\n * @param end The end of the loop extents.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(size_t index)</code> or <code>void(size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.\n **/\ntemplate <\n    typename TaskSetT,\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true,\n    std::enable_if_t<detail::CanInvoke<F(IntegerA)>::value, bool> = true>\nvoid parallel_for(\n    TaskSetT& taskSet,\n    IntegerA start,\n    IntegerB end,\n    F&& f,\n    ParForOptions options = {}) {\n  using IntegerT = std::common_type_t<IntegerA, IntegerB>;\n\n  auto range = makeChunkedRange(start, end, options.defaultChunking);\n  parallel_for(\n      taskSet,\n      range,\n      [f = std::move(f)](IntegerT s, IntegerT e) {\n        for (IntegerT i = s; i < e; ++i) {\n          f(i);\n        }\n      },\n      options);\n}\n\n/** @overload */\ntemplate <\n    typename TaskSetT,\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true,\n    std::enable_if_t<detail::CanInvoke<F(IntegerA, IntegerB)>::value, bool> = true>\nvoid parallel_for(\n    TaskSetT& taskSet,\n    IntegerA start,\n    IntegerB end,\n    F&& f,\n    ParForOptions options = {}) {\n  auto range = makeChunkedRange(start, end, options.defaultChunking);\n  parallel_for(taskSet, range, std::forward<F>(f), options);\n}\n\n/**\n * Execute loop over the range in parallel on the global thread pool and block on loop completion.\n *\n * @param start The start of the loop extents.\n * @param end The end of the loop extents.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(size_t index)</code> or <code>void(size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.  <code>options.wait</code> will always be reset\n *to true.\n **/\ntemplate <\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true>\nvoid parallel_for(IntegerA start, IntegerB end, F&& f, ParForOptions options = {}) {\n  TaskSet taskSet(globalThreadPool());\n  options.wait = true;\n  parallel_for(taskSet, start, end, std::forward<F>(f), options);\n}\n\n/**\n * Execute loop over the range in parallel.\n *\n * @param taskSet The task set to schedule the loop on.\n * @param states A container of <code>State</code> (actual type of State TBD by user).  The\n * container will be resized to hold a <code>State</code> object per executing thread.  Container\n * must provide emplace_back() and must be forward-iterable.  Examples include std::vector,\n * std::deque, and std::list.  These are the states passed into <code>f</code>, and states must\n * remain a valid object until work is completed.\n * @param defaultState A functor with signature State().  It will be called to initialize the\n * objects for <code>states</code>.\n * @param start The start of the loop extents.\n * @param end The end of the loop extents.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(State &s, size_t index)</code> or\n * <code>void(State &s, size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.\n **/\ntemplate <\n    typename TaskSetT,\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    typename StateContainer,\n    typename StateGen,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true,\n    std::enable_if_t<\n        detail::CanInvoke<F(typename StateContainer::reference, IntegerA)>::value,\n        bool> = true>\nvoid parallel_for(\n    TaskSetT& taskSet,\n    StateContainer& states,\n    const StateGen& defaultState,\n    IntegerA start,\n    IntegerB end,\n    F&& f,\n    ParForOptions options = {}) {\n  using IntegerT = std::common_type_t<IntegerA, IntegerB>;\n  auto range = makeChunkedRange(start, end, options.defaultChunking);\n  parallel_for(\n      taskSet,\n      states,\n      defaultState,\n      range,\n      [f = std::move(f)](auto& state, IntegerT s, IntegerT e) {\n        for (IntegerT i = s; i < e; ++i) {\n          f(state, i);\n        }\n      },\n      options);\n}\n\n/** @overload */\ntemplate <\n    typename TaskSetT,\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    typename StateContainer,\n    typename StateGen,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true,\n    std::enable_if_t<\n        detail::CanInvoke<F(typename StateContainer::reference, IntegerA, IntegerB)>::value,\n        bool> = true>\nvoid parallel_for(\n    TaskSetT& taskSet,\n    StateContainer& states,\n    const StateGen& defaultState,\n    IntegerA start,\n    IntegerB end,\n    F&& f,\n    ParForOptions options = {}) {\n  auto range = makeChunkedRange(start, end, options.defaultChunking);\n  parallel_for(taskSet, states, defaultState, range, std::forward<F>(f), options);\n}\n\n/**\n * Execute loop over the range in parallel on the global thread pool and block until loop\n *completion.\n *\n * @param states A container of <code>State</code> (actual type of State TBD by user).  The\n * container will be resized to hold a <code>State</code> object per executing thread.  Container\n * must provide emplace_back() and must be forward-iterable.  Examples include std::vector,\n * std::deque, and std::list.  These are the states passed into <code>f</code>, and states must\n * remain a valid object until work is completed.\n * @param defaultState A functor with signature State().  It will be called to initialize the\n * objects for <code>states</code>.\n * @param start The start of the loop extents.\n * @param end The end of the loop extents.\n * @param f The functor to execute in parallel.  Must have a signature like\n * <code>void(State &s, size_t index)</code> or\n * <code>void(State &s, size_t begin, size_t end)</code>.\n * @param options See ParForOptions for details.  <code>options.wait</code> will always be reset\n *to true.\n **/\ntemplate <\n    typename IntegerA,\n    typename IntegerB,\n    typename F,\n    typename StateContainer,\n    typename StateGen,\n    std::enable_if_t<std::is_integral<IntegerA>::value, bool> = true,\n    std::enable_if_t<std::is_integral<IntegerB>::value, bool> = true>\nvoid parallel_for(\n    StateContainer& states,\n    const StateGen& defaultState,\n    IntegerA start,\n    IntegerB end,\n    F&& f,\n    ParForOptions options = {}) {\n  TaskSet taskSet(globalThreadPool());\n  options.wait = true;\n  parallel_for(taskSet, states, defaultState, start, end, std::forward<F>(f), options);\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/pipeline.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file pipeline.h\n * @ingroup group_graph\n * A file providing utilities for parallel pipelining of work.\n **/\n\n#pragma once\n\n#include <limits>\n\n#include <dispenso/detail/pipeline_impl.h>\n\nnamespace dispenso {\n\n/**\n * OpResult is like a poor-man's std::optional for those who wish to use dispenso pipeline filtering\n * in C++14.  In C++17 and beyond, it is recommended to use std::optional instead.  OpResult has\n * implicit construct from T, just like std::optional, and move/copy constructors and operators,\n * bool conversion, and value() function, but otherwise provides less functionality than\n * std::optional.\n **/\ntemplate <typename T>\nusing OpResult = detail::OpResult<T>;\n\n/**\n * A simple constant representing maximum parallelism for a stage.  This number has no particular\n * significance, and is simply here for convenience.\n **/\nconstexpr ssize_t kStageNoLimit = std::numeric_limits<ssize_t>::max();\n\n/**\n * Create a stage for use in the pipeline function.\n *\n * @param f A function-like object that can accept the result of the previous stage (if any), and\n * which produces the output for the next stage (if any).\n * @param limit How many threads may concurrently run work for this stage.  Values larger than the\n * number of threads in the associated thread pool of the used ConcurrentTaskSet will be capped to\n * the size of the pool.\n * @return A stage object suitable for pipelining.\n **/\ntemplate <typename F>\nauto stage(F&& f, ssize_t limit) {\n  return detail::Stage<F>(std::forward<F>(f), limit);\n}\n\n/**\n * Pipeline work in stages.  Pipelines allow stages to specify parallelism limits by using the\n * <code>stage</code> function, or a function-like object can simply be passed directly, indicating\n * a serial stage.  Even if stages are serial, there can be parallelism between stages, so in a 3\n * stage serial pipeline, the expected runtime is the max of the 3 stages runtimes (note that this\n * is in the absence of pipeline overheads and with an infinitely long workstream.  In practice\n * speedup is somewhat less). This function will block until the entire pipeline has completed.\n *\n * @param pool The ThreadPool to run the work in.  This inherently determines the upper bound for\n * parallelism of the pipeline.\n * @param sIn The stages to run.  The first stage must be a Generator stage, the last must be a Sink\n * stage, and intermediate stages are Transform stages.\n * - If there is only one stage, it takes no\n * arguments, but returns a bool indicating completion (false means the pipeline is complete).\n * - Otherwise, the Generator stage takes no arguments and  must return an OpResult or std::optional\n * value, and an invalid/nullopt result indicates that the Generator is done (no more values\n * forthcoming).\n * - Transform stages should accept the output of the prior stage (or output.value() in the case of\n * OpResult or std::optional), and should return either a value or an OpResult or std::optional\n * value if the Transform is capable of filtering results. Invalid/nullopt OpResult or std::optional\n * values indicate that the value should be filtered, and not passed on to the next stage.\n * - The Sink stage should accept the output of the prior stage, just as a Transform stage does, but\n * does not return any value (or at least the pipeline will ignore it).\n *\n * @note <b>Exception behavior:</b> If a stage function throws an exception, the pipeline will stop\n * producing new work (the generator checks for exceptions between iterations) and allow any\n * already-in-flight work to complete. Queued work that has not yet started will be discarded\n * without execution. The first captured exception is rethrown from <code>pipeline()</code> when the\n * pipeline winds down. Subsequent exceptions from concurrently in-flight stages are silently\n * discarded. All internal state (concurrency counters, resource slots, completion events) is\n * cleaned up via RAII, so the thread pool remains in a valid state after an exception and may be\n * reused for subsequent pipelines. When exceptions are disabled at compile time\n * (<code>__cpp_exceptions</code> not defined), all exception-related checks are eliminated with\n * zero overhead.\n **/\ntemplate <typename... Stages>\nvoid pipeline(ThreadPool& pool, Stages&&... sIn) {\n  ConcurrentTaskSet tasks(pool);\n  auto pipes = detail::makePipes(tasks, std::forward<Stages>(sIn)...);\n  pipes.execute();\n  pipes.wait();\n}\n\n/**\n * Pipeline work in stages.  Pipelines allow stages to specify parallelism limits by using the\n * <code>stage</code> function, or a function-like object can simply be passed directly, indicating\n * a serial stage.  Even if stages are serial, there can be parallelism between stages, so in a 3\n * stage serial pipeline, the expected runtime is the max of the 3 stages runtimes (note that this\n * is in the absence of pipeline overheads and with an infinitely long workstream.  In practice\n * speedup is somewhat less). Work will be run on dispenso's global thread pool.  This function will\n * block until the entire pipeline has completed.\n *\n * @param sIn The stages to run.  The first stage must be a Generator stage, the last must be a Sink\n * stage, and intermediate stages are Transform stages.\n * - If there is only one stage, it takes no\n * arguments, but returns a bool indicating completion (false means the pipeline is complete).\n * - Otherwise, the Generator stage takes no arguments and  must return an OpResult or std::optional\n * value, and an invalid/nullopt result indicates that the Generator is done (no more values\n * forthcoming).\n * - Transform stages should accept the output of the prior stage (or output.value() in the case of\n * OpResult or std::optional), and should return either a value or an OpResult or std::optional\n * value if the Transform is capable of filtering results. Invalid/nullopt OpResult or std::optional\n * values indicate that the value should be filtered, and not passed on to the next stage.\n * - The Sink stage should accept the output of the prior stage, just as a Transform stage does, but\n * does not return any value (or at least the pipeline will ignore it).\n *\n * @note See the ThreadPool overload of <code>pipeline()</code> for exception behavior details.\n **/\ntemplate <typename... Stages>\nvoid pipeline(Stages&&... sIn) {\n  pipeline(globalThreadPool(), std::forward<Stages>(sIn)...);\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/platform.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file platform.h\n * @ingroup group_util\n * Platform constants and common utilities.\n **/\n\n#pragma once\n#include <algorithm>\n#include <atomic>\n#include <cassert>\n#include <cstdlib>\n#include <memory>\n#include <thread>\n#include <type_traits>\n\n#if defined(_MSC_VER) && \\\n    (defined(_M_AMD64) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_ARM))\n#include <intrin.h>\n#endif\n\nnamespace dispenso {\n\n#define DISPENSO_MAJOR_VERSION 1\n#define DISPENSO_MINOR_VERSION 5\n#define DISPENSO_PATCH_VERSION 1\n\n// C++20 concepts support detection\n#if __cplusplus >= 202002L && defined(__cpp_concepts) && __cpp_concepts >= 201907L\n#define DISPENSO_HAS_CONCEPTS 1\n#include <concepts>\n#else\n#define DISPENSO_HAS_CONCEPTS 0\n#endif\n\n/**\n * @def DISPENSO_REQUIRES\n * @brief Macro for conditionally applying C++20 concept constraints.\n *\n * On C++20 with concepts support, this expands to a requires clause.\n * On C++14/17, this expands to nothing, maintaining backward compatibility.\n *\n * Example usage:\n * @code\n * template <typename F>\n * DISPENSO_REQUIRES(std::invocable<F>)\n * void schedule(F&& f);\n * @endcode\n **/\n#if DISPENSO_HAS_CONCEPTS\n#define DISPENSO_REQUIRES(...) requires(__VA_ARGS__)\n#else\n#define DISPENSO_REQUIRES(...)\n#endif\n\n#if defined(DISPENSO_SHARED_LIB)\n#if defined _WIN32\n\n#if defined(DISPENSO_LIB_EXPORT)\n#define DISPENSO_DLL_ACCESS __declspec(dllexport)\n#else\n#define DISPENSO_DLL_ACCESS __declspec(dllimport)\n#endif // DISPENSO_LIB_EXPORT\n\n#elif defined(__clang__) || defined(__GNUC__)\n#define DISPENSO_DLL_ACCESS __attribute__((visibility(\"default\")))\n#endif // PLATFORM\n#endif // DISPENSO_SHARED_LIB\n\n#if !defined(DISPENSO_DLL_ACCESS)\n#define DISPENSO_DLL_ACCESS\n#endif // DISPENSO_DLL_ACCESS\n\nusing ssize_t = std::make_signed<std::size_t>::type;\n\n#if defined(__clang__) || defined(__GNUC__)\n#define DISPENSO_INLINE __attribute__((always_inline)) inline\n#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)\n#define DISPENSO_INLINE __forceinline\n#else\n#define DISPENSO_INLINE inline\n#endif // PLATFORM\n\n/**\n * @var constexpr size_t kCacheLineSize\n * @brief A constant that defines a safe number of bytes+alignment to avoid false sharing.\n **/\n#if defined(__APPLE__) && defined(__arm64__)\nconstexpr size_t kCacheLineSize = 128;\n#else\nconstexpr size_t kCacheLineSize = 64;\n#endif\n\n/**\n * @def DISPENSO_THREAD_LOCAL\n * @brief A macro that can be used when declaring a lightweight thread-local variable.\n **/\n\n// TODO(bbudge): Non-gcc/clang/msvc platforms.\n#if defined(_MSC_VER)\n#define DISPENSO_THREAD_LOCAL __declspec(thread)\n#elif defined(__GNUC__) || defined(__clang__)\n#define DISPENSO_THREAD_LOCAL __thread\n#else\n#error Supply lightweight thread-locals for this compiler.  Can define to thread_local if lightweight not available\n#endif\n\n#if (defined(__GNUC__) || defined(__clang__))\n#define DISPENSO_EXPECT(a, b) __builtin_expect(a, b)\n#else\n#define DISPENSO_EXPECT(a, b) a\n#endif\n\n// clang-format off\n#if (defined(__GNUC__) || defined(__clang__))\n#define DO_PRAGMA(X) _Pragma(#X)\n#define DISPENSO_DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostic push)\n#define DISPENSO_DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop)\n#define DISPENSO_DISABLE_WARNING(warningName) DO_PRAGMA(GCC diagnostic ignored #warningName)\n#if !defined(__clang__)\n#define DISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\n#define DISPENSO_DISABLE_WARNING_GLOBAL_CONSTRUCTORS\n#else\n#define DISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS \\\n  DISPENSO_DISABLE_WARNING(-Wgnu-zero-variadic-macro-arguments)\n#define DISPENSO_DISABLE_WARNING_GLOBAL_CONSTRUCTORS \\\n  DISPENSO_DISABLE_WARNING(-Wglobal-constructors)\n#endif\n#elif defined(_MSC_VER)\n#define DISPENSO_DISABLE_WARNING_PUSH __pragma(warning(push))\n#define DISPENSO_DISABLE_WARNING_POP __pragma(warning(pop))\n#define DISPENSO_DISABLE_WARNING(warningNumber) __pragma(warning(disable : warningNumber))\n#define DISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\n#define DISPENSO_DISABLE_WARNING_GLOBAL_CONSTRUCTORS\n#else\n#define DISPENSO_DISABLE_WARNING_PUSH\n#define DISPENSO_DISABLE_WARNING_POP\n#define DISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\n#define DISPENSO_DISABLE_WARNING_GLOBAL_CONSTRUCTORS\n#endif\n// clang-format on\n\n/**\n * A wrapper that aligns the contained value to cache line boundaries.\n *\n * Useful for avoiding false sharing in concurrent data structures.\n *\n * @tparam T The type to wrap with cache line alignment.\n */\ntemplate <typename T>\nclass CacheAligned {\n public:\n  CacheAligned() = default;\n  /** Construct from a value. @param t The value to wrap. */\n  CacheAligned(T t) : t_(t) {}\n  operator T&() {\n    return t_;\n  }\n\n  operator const T&() const {\n    return t_;\n  }\n\n private:\n  alignas(kCacheLineSize) T t_;\n};\n\nnamespace detail {\n\ntemplate <typename T>\nstruct AlignedBuffer {\n  alignas(alignof(T)) char b[sizeof(T)];\n};\n\ntemplate <typename T>\nstruct alignas(kCacheLineSize) AlignedAtomic : public std::atomic<T*> {};\n\ninline void* alignedMalloc(size_t bytes, size_t alignment) {\n  alignment = std::max(alignment, sizeof(uintptr_t));\n  char* ptr = reinterpret_cast<char*>(::malloc(bytes + alignment));\n  uintptr_t base = reinterpret_cast<uintptr_t>(ptr);\n  uintptr_t oldBase = base;\n  uintptr_t mask = alignment - 1;\n  base += alignment;\n  base &= ~mask;\n\n  uintptr_t* recovery = reinterpret_cast<uintptr_t*>(base - sizeof(uintptr_t));\n  *recovery = oldBase;\n  return reinterpret_cast<void*>(base);\n}\n\ninline void* alignedMalloc(size_t bytes) {\n  return alignedMalloc(bytes, kCacheLineSize);\n}\n\ninline void alignedFree(void* ptr) {\n  if (!ptr) {\n    return;\n  }\n  char* p = reinterpret_cast<char*>(ptr);\n  uintptr_t recovered = *reinterpret_cast<uintptr_t*>(p - sizeof(uintptr_t));\n  ::free(reinterpret_cast<void*>(recovered));\n}\n\ntemplate <typename T>\nstruct AlignedFreeDeleter {\n  void operator()(T* ptr) {\n    ptr->~T();\n    detail::alignedFree(ptr);\n  }\n};\ntemplate <>\nstruct AlignedFreeDeleter<void> {\n  void operator()(void* ptr) {\n    detail::alignedFree(ptr);\n  }\n};\n\ntemplate <typename T, class... Args>\nstd::shared_ptr<T> make_shared(Args&&... args) {\n  void* tv = alignedMalloc(sizeof(T), alignof(T));\n  T* t = new (tv) T(std::forward<Args>(args)...);\n  return std::shared_ptr<T>(t, AlignedFreeDeleter<T>());\n}\n\ninline constexpr uintptr_t alignToCacheLine(uintptr_t val) {\n  constexpr uintptr_t kMask = kCacheLineSize - 1;\n  val += kMask;\n  val &= ~kMask;\n  return val;\n}\n\n#if defined __x86_64__ || defined __i386__\ninline void cpuRelax() {\n  asm volatile(\"pause\" ::: \"memory\");\n}\n#elif defined _MSC_VER && (defined _M_AMD64 || defined _M_IX86)\ninline void cpuRelax() {\n  _mm_pause();\n}\n#elif defined __arm64__ || defined __aarch64__\ninline void cpuRelax() {\n  asm volatile(\"yield\" ::: \"memory\");\n}\n#elif defined _MSC_VER && (defined _M_ARM64 || defined _M_ARM)\ninline void cpuRelax() {\n  __yield();\n}\n#elif defined __powerpc__ || defined __POWERPC__\n#if defined __APPLE__\ninline void cpuRelax() {\n  asm volatile(\"or r27,r27,r27\" ::: \"memory\");\n}\n#else\ninline void cpuRelax() {\n  asm volatile(\"or 27,27,27\" ::: \"memory\");\n}\n#endif // APPLE\n#else\n// TODO: provide reasonable relax on other archs.\ninline void cpuRelax() {}\n#endif // ARCH\n\n// When statically chunking a range, it is generally not possible to use a single chunk size plus\n// remainder and get a good load distribution.  By estimating too high, we can have idle threads. By\n// estimating too low, the remainder can be several times as large as the chunk for other threads.\n// Instead, we compute the chunk size that is the ceil of the fractional chunk size.  That can be\n// used for the first transitionIndex values, while the remaining (chunks - transitionTaskIndex)\n// values will be ceilChunkSize - 1.\nstruct StaticChunking {\n  ssize_t transitionTaskIndex;\n  ssize_t ceilChunkSize;\n};\n\ninline StaticChunking staticChunkSize(ssize_t items, ssize_t chunks) {\n  assert(chunks > 0);\n  StaticChunking chunking;\n  chunking.ceilChunkSize = (items + chunks - 1) / chunks;\n  ssize_t numLeft = chunking.ceilChunkSize * chunks - items;\n  chunking.transitionTaskIndex = chunks - numLeft;\n  return chunking;\n}\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/pool_allocator.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/pool_allocator.h>\n\nnamespace dispenso {\n\ntemplate <bool kThreadSafe>\nPoolAllocatorT<kThreadSafe>::PoolAllocatorT(\n    size_t chunkSize,\n    size_t allocSize,\n    std::function<void*(size_t)> allocFunc,\n    std::function<void(void*)> deallocFunc)\n    : chunkSize_(chunkSize),\n      allocSize_(allocSize),\n      chunksPerAlloc_(allocSize / chunkSize),\n      allocFunc_(std::move(allocFunc)),\n      deallocFunc_(std::move(deallocFunc)) {\n  // Start off with at least enough space to store at least one set of chunks.\n  chunks_.reserve(chunksPerAlloc_);\n}\n\ntemplate <bool kThreadSafe>\nchar* PoolAllocatorT<kThreadSafe>::alloc() {\n  while (true) {\n    uint32_t allocId = 0;\n    if (kThreadSafe) {\n      allocId = backingAllocLock_.fetch_or(1, std::memory_order_acquire);\n    }\n\n    if (allocId == 0) {\n      if (chunks_.empty()) {\n        char* buffer;\n        if (backingAllocs2_.empty()) {\n          buffer = reinterpret_cast<char*>(allocFunc_(allocSize_));\n        } else {\n          buffer = backingAllocs2_.back();\n          backingAllocs2_.pop_back();\n        }\n        backingAllocs_.push_back(buffer);\n        // Push n-1 values into the chunks_ buffer, and then return the nth.\n        for (size_t i = 0; i < chunksPerAlloc_ - 1; ++i) {\n          chunks_.push_back(buffer);\n          buffer += chunkSize_;\n        }\n        if (kThreadSafe) {\n          backingAllocLock_.store(0, std::memory_order_release);\n        }\n        return buffer;\n      }\n      char* back = chunks_.back();\n      chunks_.pop_back();\n      if (kThreadSafe) {\n        backingAllocLock_.store(0, std::memory_order_release);\n      }\n      return back;\n    } else {\n      std::this_thread::yield();\n    }\n  }\n}\n\ntemplate <bool kThreadSafe>\nvoid PoolAllocatorT<kThreadSafe>::dealloc(char* ptr) {\n  // For now do not release any memory back to the deallocFunc until destruction.\n  // TODO(bbudge): Consider cases where we haven't gotten below some threshold of ready chunks\n  // in a while.  In that case, we could begin tracking allocations, and try to assemble entire\n  // starting allocations, possibly deferring a small amount to each alloc call.  This would be\n  // slower, but would ensure we don't get into a situation where we need a bunch of memory up\n  // front, and then never again.\n\n  while (true) {\n    uint32_t allocId = 0;\n    if (kThreadSafe) {\n      allocId = backingAllocLock_.fetch_or(1, std::memory_order_acquire);\n    }\n    if (allocId == 0) {\n      chunks_.push_back(ptr);\n      if (kThreadSafe) {\n        backingAllocLock_.store(0, std::memory_order_release);\n      }\n      break;\n    }\n  }\n}\n\ntemplate <bool kThreadSafe>\nvoid PoolAllocatorT<kThreadSafe>::clear() {\n  chunks_.clear();\n  if (backingAllocs2_.size() < backingAllocs_.size()) {\n    std::swap(backingAllocs2_, backingAllocs_);\n  }\n  for (char* ba : backingAllocs_) {\n    backingAllocs2_.push_back(ba);\n  }\n  backingAllocs_.clear();\n}\n\ntemplate <bool kThreadSafe>\nPoolAllocatorT<kThreadSafe>::~PoolAllocatorT() {\n  for (char* backing : backingAllocs_) {\n    deallocFunc_(backing);\n  }\n  for (char* backing : backingAllocs2_) {\n    deallocFunc_(backing);\n  }\n}\n\ntemplate class PoolAllocatorT<false>;\ntemplate class PoolAllocatorT<true>;\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/pool_allocator.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file pool_allocator.h\n * @ingroup group_alloc\n * A pool allocator to help reduce calls to the underlying allocation and deallocation functions\n * that can be provided custom backing allocation and deallocation functions, e.g. cudaMalloc,\n * cudaFree.\n **/\n\n#pragma once\n\n#include <atomic>\n#include <functional>\n#include <vector>\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * A pool allocator to help reduce calls to the underlying allocation and deallocation functions.\n **/\ntemplate <bool kThreadSafe>\nclass PoolAllocatorT {\n public:\n  /**\n   * Construct a PoolAllocator.\n   *\n   * @param chunkSize The chunk size for each pool allocation\n   * @param allocSize The size of underlying slabs to be chunked\n   * @param allocFunc The underlying allocation function for allocating slabs\n   * @param deallocFunc The underlying deallocation function.  Currently only called on destruction.\n   **/\n  DISPENSO_DLL_ACCESS PoolAllocatorT(\n      size_t chunkSize,\n      size_t allocSize,\n      std::function<void*(size_t)> allocFunc,\n      std::function<void(void*)> deallocFunc);\n\n  /**\n   * Allocate a chunk from a slab\n   *\n   * @return The pointer to a buffer of chunkSize bytes\n   **/\n  DISPENSO_DLL_ACCESS char* alloc();\n\n  /**\n   * Deallocate a previously allocated chunk\n   *\n   * @param ptr The chunk to return to the available pool\n   **/\n  DISPENSO_DLL_ACCESS void dealloc(char* ptr);\n\n  /**\n   * Effectively dealloc all previously allocated chunks.  Useful for arenas.\n   * This function is not thread safe, and no previously allocated chunks may be dealloc'd after\n   * clear.\n   **/\n  DISPENSO_DLL_ACCESS void clear();\n\n  /**\n   * Get the total capicity allocated in chunks (how many alloc() could be called without triggering\n   * allocFunc() if all chunks were available)\n   **/\n  size_t totalChunkCapacity() const {\n    return (backingAllocs2_.size() + backingAllocs_.size()) * chunksPerAlloc_;\n  }\n  /**\n   * Destruct a PoolAllocator\n   **/\n  DISPENSO_DLL_ACCESS ~PoolAllocatorT();\n\n private:\n  const size_t chunkSize_;\n  const size_t allocSize_;\n  const size_t chunksPerAlloc_;\n\n  std::function<void*(size_t)> allocFunc_;\n  std::function<void(void*)> deallocFunc_;\n\n  // Use of a spin lock was found to be faster than std::mutex in benchmarks.\n  alignas(kCacheLineSize) std::atomic<uint32_t> backingAllocLock_{0};\n  std::vector<char*> backingAllocs_;\n  std::vector<char*> backingAllocs2_;\n\n  std::vector<char*> chunks_;\n};\n\n/** Thread-safe pool allocator with internal locking. */\nusing PoolAllocator = PoolAllocatorT<true>;\n/** Pool allocator without locking, for single-threaded use or external synchronization. */\nusing NoLockPoolAllocator = PoolAllocatorT<false>;\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/priority.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/priority.h>\n\n#if (defined(__unix__) || defined(unix)) && !defined(USG)\n#include <sys/param.h>\n#endif\n\n#if defined(__linux__)\n#include <pthread.h>\n#include <sys/resource.h>\n#include <unistd.h>\n#elif defined(__MACH__)\n#include <mach/mach_time.h>\n#include <mach/thread_act.h>\n#include <pthread.h>\n#elif defined(_WIN32)\n#include <Windows.h>\n#elif defined(BSD)\n#include <sys/rtprio.h>\n#include <sys/types.h>\n#endif\n\nnamespace dispenso {\n\nnamespace {\nDISPENSO_THREAD_LOCAL ThreadPriority g_threadPriority = ThreadPriority::kNormal;\n} // namespace\n\nThreadPriority getCurrentThreadPriority() {\n  return g_threadPriority;\n}\n\n#ifdef __MACH__\nbool setCurrentThreadPriority(ThreadPriority prio) {\n  mach_port_t threadport = pthread_mach_thread_np(pthread_self());\n  if (prio == ThreadPriority::kRealtime) {\n    mach_timebase_info_data_t info;\n    mach_timebase_info(&info);\n    double msToAbsTime = ((double)info.denom / (double)info.numer) * 1000000.0;\n    thread_time_constraint_policy_data_t time_constraints;\n    time_constraints.period = 0;\n    time_constraints.computation = static_cast<uint32_t>(1.0 * msToAbsTime);\n    time_constraints.constraint = static_cast<uint32_t>(10.0 * msToAbsTime);\n    time_constraints.preemptible = 0;\n\n    if (thread_policy_set(\n            threadport,\n            THREAD_TIME_CONSTRAINT_POLICY,\n            (thread_policy_t)&time_constraints,\n            THREAD_TIME_CONSTRAINT_POLICY_COUNT) != KERN_SUCCESS) {\n      return false;\n    }\n  }\n\n  // https://fergofrog.com/code/cbowser/xnu/osfmk/kern/sched.h.html#_M/MAXPRI_USER\n  struct thread_precedence_policy ttcpolicy;\n\n  switch (prio) {\n    case ThreadPriority::kLow:\n      ttcpolicy.importance = 20;\n      break;\n    case ThreadPriority::kNormal:\n      ttcpolicy.importance = 37;\n      break;\n    case ThreadPriority::kHigh: // fallthrough\n    case ThreadPriority::kRealtime:\n      ttcpolicy.importance = 63;\n      break;\n  }\n\n  if (thread_policy_set(\n          threadport,\n          THREAD_PRECEDENCE_POLICY,\n          (thread_policy_t)&ttcpolicy,\n          THREAD_PRECEDENCE_POLICY_COUNT) != KERN_SUCCESS) {\n    return false;\n  }\n\n  g_threadPriority = prio;\n  return true;\n}\n#elif defined(_WIN32)\n// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority\nbool setCurrentThreadPriority(ThreadPriority prio) {\n  if (prio == ThreadPriority::kRealtime) {\n    if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {\n      return false;\n    }\n  }\n\n  if (prio == ThreadPriority::kHigh) {\n    // Best effort\n    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);\n  }\n\n  bool success = false;\n  switch (prio) {\n    case ThreadPriority::kLow:\n      success = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);\n      break;\n    case ThreadPriority::kNormal:\n      success = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);\n      break;\n    case ThreadPriority::kHigh: // fallthrough\n    case ThreadPriority::kRealtime:\n      success = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);\n      break;\n  }\n\n  if (!success) {\n    return false;\n  }\n\n  g_threadPriority = prio;\n  return true;\n}\n#elif defined(__linux__)\nbool setCurrentThreadPriority(ThreadPriority prio) {\n  if (prio == ThreadPriority::kRealtime) {\n    struct sched_param param;\n    param.sched_priority = 99;\n    if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &param)) {\n      return false;\n    }\n  }\n\n  switch (prio) {\n    case ThreadPriority::kLow:\n      errno = 0;\n      (void)!nice(10);\n      break;\n    case ThreadPriority::kNormal:\n      errno = 0;\n      (void)!nice(0);\n      break;\n    case ThreadPriority::kHigh: // fallthrough\n    case ThreadPriority::kRealtime: {\n      struct rlimit rlim;\n      getrlimit(RLIMIT_NICE, &rlim);\n      if (rlim.rlim_max <= 20) {\n        return false;\n      }\n      rlim.rlim_cur = rlim.rlim_max;\n      setrlimit(RLIMIT_NICE, &rlim);\n      errno = 0;\n      (void)!nice(static_cast<int>(20 - rlim.rlim_max));\n    }\n  }\n  if (errno != 0) {\n    return false;\n  }\n  g_threadPriority = prio;\n  return true;\n}\n#elif defined(__FreeBSD__)\n// TODO: Find someone who has a FreeBSD system to test this code.\nbool setCurrentThreadPriority(ThreadPriority prio) {\n  struct rtprio rtp;\n\n  if (prio == ThreadPriority::kRealtime) {\n    rtp.type = RTP_PRIO_REALTIME;\n    rtp.prio = 10;\n    if (rtprio_thread(RTP_SET, 0, &rtp)) {\n      return false;\n    }\n  } else {\n    rtp.type = RTP_PRIO_NORMAL;\n    switch (prio) {\n      case ThreadPriority::kLow:\n        rtp.prio = 31;\n        break;\n      case ThreadPriority::kNormal:\n        rtp.prio = 15;\n        break;\n      case ThreadPriority::kHigh: // fallthrough\n      case ThreadPriority::kRealtime:\n        rtp.prio = 0;\n        break;\n    }\n    if (rtprio_thread(RTP_SET, 0, &rtp)) {\n      return false;\n    }\n  }\n  g_threadPriority = prio;\n  return true;\n}\n#else\nbool setCurrentThreadPriority(ThreadPriority prio) {\n  return false;\n}\n\n#endif // platform\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/priority.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file priority.h\n * @ingroup group_util\n *\n * Utilities for getting and setting thread priority.  This is an attempt to unify concepts for\n * thread priority usefully across multiple platforms.  For finer control, use platform specific\n * functionality.\n *\n * @note When using higher-than-normal priority, use caution!  Too many threads running at too high\n * priority can have a strong negative impact on the responsivity of the machine.  Prefer to use\n * realtime priority only for short running tasks that need to be very responsively run.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * A thread priority setting.  Enum values in increasing order of priority.\n **/\nenum class ThreadPriority { kLow, kNormal, kHigh, kRealtime };\n\n/**\n * Access the current thread priority as set by setCurrentThreadPriority.\n *\n * @return The priority of the current thread\n *\n * @note If the current thread priority has been set via a platform-specific mechanism, this may\n * return an incorrect value.\n **/\nDISPENSO_DLL_ACCESS ThreadPriority getCurrentThreadPriority();\n\n/**\n * Set the current thread's priority\n *\n * @param prio The priority to set to\n *\n * @return true if the priority was modified, false otherwise.\n **/\nDISPENSO_DLL_ACCESS bool setCurrentThreadPriority(ThreadPriority prio);\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/resource_pool.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file resource_pool.h\n * @ingroup group_containers\n * A file providing ResourcePool.  This is syntactic sugar over what is essentially a set of\n * semaphore guarded resources.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n#include <dispenso/tsan_annotations.h>\n#include <moodycamel/blockingconcurrentqueue.h>\n\nnamespace dispenso {\n\ntemplate <typename T>\nclass ResourcePool;\n\n/**\n * A RIAA wrapper for a user's type that can manage accessibility and ensures the resource will go\n * back into the ResourcePool upon destruction.\n **/\ntemplate <typename T>\nclass Resource {\n public:\n  /** Move constructor. */\n  Resource(Resource&& other) : resource_(other.resource_), pool_(other.pool_) {\n    other.resource_ = nullptr;\n  }\n\n  Resource& operator=(Resource&& other) {\n    if (&other != this) {\n      recycle();\n      resource_ = other.resource_;\n      pool_ = other.pool_;\n      other.resource_ = nullptr;\n    }\n    return *this;\n  }\n\n  /**\n   * Access the underlying resource object.\n   *\n   * @return a reference to the resource.\n   **/\n  T& get() {\n    return *resource_;\n  }\n\n  ~Resource() {\n    recycle();\n  }\n\n private:\n  Resource(T* res, ResourcePool<T>* pool) : resource_(res), pool_(pool) {}\n\n  void recycle();\n\n  T* resource_;\n  ResourcePool<T>* pool_;\n\n  friend class ResourcePool<T>;\n};\n\n/**\n * A pool of resources that can be accessed from multiple threads.  This is akin to a set of\n * resources and a semaphore ensuring enough resources exist.\n **/\ntemplate <typename T>\nclass ResourcePool {\n public:\n  /**\n   * Construct a ResourcePool.\n   *\n   * @param size The number of <code>T</code> objects in the pool.\n   * @param init A functor with signature T() which can be called to initialize the pool's\n   * resources.\n   **/\n  template <typename F>\n  ResourcePool(size_t size, const F& init)\n      : pool_(size),\n        backingResources_(\n            reinterpret_cast<char*>(\n                detail::alignedMalloc(size * detail::alignToCacheLine(sizeof(T))))),\n        size_(size) {\n    char* buf = backingResources_;\n\n    // There are three reasons we create our own buffer and use placement new:\n    // 1. We want to be able to handle non-movable non-copyable objects\n    //   * Note that we could do this with std::deque\n    // 2. We want to minimize memory allocations, since that can be a common point of contention in\n    //    multithreaded programs.\n    // 3. We can easily ensure that the objects are cache aligned to help avoid false sharing.\n\n    for (size_t i = 0; i < size; ++i) {\n      pool_.enqueue(new (buf) T(init()));\n      buf += detail::alignToCacheLine(sizeof(T));\n    }\n  }\n\n  /**\n   * Acquire a resource from the pool.  This function may block until a resource becomes available.\n   *\n   * @return a <code>Resource</code>-wrapped resource.\n   **/\n  Resource<T> acquire() {\n    T* t;\n    DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n    pool_.wait_dequeue(t);\n    DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n    return Resource<T>(t, this);\n  }\n\n  /**\n   * Destruct the ResourcePool.  The user must ensure that all resources are returned to the pool\n   * prior to destroying the pool.\n   **/\n  ~ResourcePool() {\n    assert(pool_.size_approx() == size_);\n    for (size_t i = 0; i < size_; ++i) {\n      T* t;\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n      pool_.wait_dequeue(t);\n      DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n      t->~T();\n    }\n    detail::alignedFree(backingResources_);\n  }\n\n private:\n  void recycle(T* t) {\n    DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n    pool_.enqueue(t);\n    DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n  }\n\n  moodycamel::BlockingConcurrentQueue<T*> pool_;\n  char* backingResources_;\n  size_t size_;\n\n  friend class Resource<T>;\n};\n\ntemplate <typename T>\nvoid Resource<T>::recycle() {\n  if (resource_) {\n    pool_->recycle(resource_);\n  }\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/rw_lock.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file rw_lock.h\n * @ingroup group_sync\n * A file providing RWLock, a reader/writer lock interface.\n **/\n\n#include <dispenso/detail/rw_lock_impl.h>\n\nnamespace dispenso {\n\n/**\n * A reader/writer lock interface compatible with std::shared_mutex (for use with std::unique_lock\n * and std::shared_lock).  The interface is designed to be very fast in the face of high levels of\n * contention for high read traffic and low write traffic.\n *\n * @note RWLock is not as fully-featured as std::shared_mutex: It does not go to the OS to wait.\n * This behavior is good for guarding very fast operations, but less good for guarding very slow\n * operations.  Additionally, RWLock is not compatible with std::condition_variable, though\n * std::condition_variable_any may work (untested).  It could be possible to extend RWLock with it's\n * own ConditionVariable, make waiting operations sleep in the OS, and also to add timed functions;\n * however those may slow things down in the fast case.  If some/all of that functionality is\n * needed, use std::shared_mutex, or develop a new type.\n **/\nclass alignas(kCacheLineSize) RWLock : public detail::RWLockImpl {\n public:\n  /**\n   * Locks for write access\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  using detail::RWLockImpl::lock;\n\n  /**\n   * Tries to lock for write access, returns if unable to lock\n   *\n   * @return true if lock was acquired, false otherwise\n   **/\n  using detail::RWLockImpl::try_lock;\n\n  /**\n   * Unlocks write access\n   *\n   * @note Must already be locked by the current thread of execution, otherwise, the behavior is\n   * undefined.\n   **/\n  using detail::RWLockImpl::unlock;\n\n  /**\n   * Locks for read access\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  using detail::RWLockImpl::lock_shared;\n\n  /**\n   * Tries to lock for read access, returns if unable to lock\n   *\n   * @return true if lock was acquired, false otherwise\n   *\n   * @note It is undefined behavior to recursively lock\n   **/\n  using detail::RWLockImpl::try_lock_shared;\n\n  /**\n   * Unlocks read access\n   *\n   * @note Must already be locked by the current thread of execution, otherwise, the behavior is\n   * undefined.\n   **/\n  using detail::RWLockImpl::unlock_shared;\n\n  /**\n   * Upgrade from a reader lock to a writer lock.  lock_upgrade is a power-user interface.  There is\n   * a very good reason why it is not exposed as upgrade_mutex in the standard.  To use it safely,\n   * you *MUST* ensure only one thread can try to lock for write concurrently.  If that cannot be\n   * guaranteed, you should unlock for read, and lock for write instead of using lock_upgrade to\n   * avoid potential deadlock.\n   *\n   * @note Calling this if the writer lock is already held, or if no reader lock is already held is\n   * undefined behavior.\n   **/\n  using detail::RWLockImpl::lock_upgrade;\n\n  /**\n   * Downgrade the lock from a writer lock to a reader lock.\n   *\n   * @note Calling this if the writer lock is not held results in undefined behavior\n   **/\n  using detail::RWLockImpl::lock_downgrade;\n};\n\n/**\n * An unaligned version of the RWLock.  This could be useful if you e.g. want to create an array of\n * these to guard a large number of slots, and the likelihood of multiple threads touching any\n * region concurrently is low.  All other behavior remains the same, so refer to the documentation\n * for RWLock.\n **/\nclass UnalignedRWLock : public detail::RWLockImpl {};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/schedulable.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file schedulable.h\n * @ingroup group_core\n * Classes providing simple schedulables that match scheduling interfaces of *TaskSet and ThreadPool\n *\n **/\n\n#pragma once\n\n#include <dispenso/detail/completion_event_impl.h>\n#include <dispenso/task_set.h>\n\nnamespace dispenso {\n\n/**\n * A class fullfilling the Schedulable concept that immediately invokes the functor.  This can be\n * used in place of <code>ThreadPool</code> or <code>TaskSet</code> with <code>Future</code>s at\n * construction or through <code>then</code>, or it may be used in TimedTask scheduling for\n * short-running tasks.\n **/\nclass ImmediateInvoker {\n public:\n  /**\n   * Schedule a functor to be executed.  It will be invoked immediately.\n   *\n   * @param f The functor to be executed.  <code>f</code>'s signature must match void().  Best\n   * performance will come from passing lambdas, other concrete functors, or OnceFunction, but\n   * std::function or similarly type-erased objects will also work.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f) const {\n    f();\n  }\n\n  /**\n   * Schedule a functor to be executed.  It is a bit oxymoronical to call this function, since\n   * ForceQueuingTag will have no effect, and it's use is discouraged.\n   *\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, ForceQueuingTag) const {\n    f();\n  }\n};\n\nconstexpr ImmediateInvoker kImmediateInvoker;\n\n/**\n * A class fullfilling the Schedulable concept that always invokes on a new thread.  This can be\n * used in place of <code>ThreadPool</code> or <code>TaskSet</code> with <code>Future</code>s at\n * construction or through <code>then</code>.\n **/\nclass NewThreadInvoker {\n public:\n  /**\n   * Schedule a functor to be executed on a new thread.\n   *\n   * @param f The functor to be executed.  <code>f</code>'s signature must match void().  Best\n   * performance will come from passing lambdas, other concrete functors, or OnceFunction, but\n   * std::function or similarly type-erased objects will also work.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f) const {\n    schedule(std::forward<F>(f), ForceQueuingTag());\n  }\n  /**\n   * Schedule a functor to be executed on a new thread.\n   *\n   * @param f The functor to be executed.  <code>f</code>'s signature must match void().  Best\n   * performance will come from passing lambdas, other concrete functors, or OnceFunction, but\n   * std::function or similarly type-erased objects will also work.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, ForceQueuingTag) const {\n    std::thread thread([f = std::move(f)]() { f(); });\n    thread.detach();\n  }\n\n private:\n};\n\nconstexpr NewThreadInvoker kNewThreadInvoker;\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/small_buffer_allocator.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/detail/small_buffer_allocator_impl.h>\n#include <dispenso/small_buffer_allocator.h>\n\n#include <new>\n\nnamespace dispenso {\nnamespace detail {\n\ntemplate <size_t kChunkSize>\nSmallBufferGlobals& getSmallBufferGlobals() {\n  // controlled leak here\n  static SmallBufferGlobals* globals = new SmallBufferGlobals();\n  return *globals;\n}\n\nchar* allocSmallBufferImpl(size_t ordinal) {\n  switch (ordinal) {\n    case 0:\n      return detail::SmallBufferAllocator<4>::alloc();\n    case 1:\n      return detail::SmallBufferAllocator<8>::alloc();\n    case 2:\n      return detail::SmallBufferAllocator<16>::alloc();\n    case 3:\n      return detail::SmallBufferAllocator<32>::alloc();\n    case 4:\n      return detail::SmallBufferAllocator<64>::alloc();\n    case 5:\n      return detail::SmallBufferAllocator<128>::alloc();\n    case 6:\n      return detail::SmallBufferAllocator<256>::alloc();\n    default:\n      assert(false && \"Invalid small buffer ordinal requested\");\n      return nullptr;\n  }\n}\n\nvoid deallocSmallBufferImpl(size_t ordinal, void* buf) {\n  switch (ordinal) {\n    case 0:\n      detail::SmallBufferAllocator<4>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 1:\n      detail::SmallBufferAllocator<8>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 2:\n      detail::SmallBufferAllocator<16>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 3:\n      detail::SmallBufferAllocator<32>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 4:\n      detail::SmallBufferAllocator<64>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 5:\n      detail::SmallBufferAllocator<128>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    case 6:\n      detail::SmallBufferAllocator<256>::dealloc(reinterpret_cast<char*>(buf));\n      break;\n    default:\n      assert(false && \"Invalid small buffer ordinal requested\");\n  }\n}\n\nsize_t approxBytesAllocatedSmallBufferImpl(size_t ordinal) {\n  switch (ordinal) {\n    case 0:\n      return detail::SmallBufferAllocator<4>::bytesAllocated();\n    case 1:\n      return detail::SmallBufferAllocator<8>::bytesAllocated();\n    case 2:\n      return detail::SmallBufferAllocator<16>::bytesAllocated();\n    case 3:\n      return detail::SmallBufferAllocator<32>::bytesAllocated();\n    case 4:\n      return detail::SmallBufferAllocator<64>::bytesAllocated();\n    case 5:\n      return detail::SmallBufferAllocator<128>::bytesAllocated();\n    case 6:\n      return detail::SmallBufferAllocator<256>::bytesAllocated();\n    default:\n      assert(false && \"Invalid small buffer ordinal requested\");\n      return 0;\n  }\n}\n\ntemplate <size_t kChunkSize>\nSmallBufferAllocator<kChunkSize>::PerThreadQueuingData::~PerThreadQueuingData() {\n  enqueue_bulk(buffers_, count_);\n\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n  ptoken().~ProducerToken();\n  ctoken().~ConsumerToken();\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n}\n\ntemplate class SmallBufferAllocator<4>;\ntemplate class SmallBufferAllocator<8>;\ntemplate class SmallBufferAllocator<16>;\ntemplate class SmallBufferAllocator<32>;\ntemplate class SmallBufferAllocator<64>;\ntemplate class SmallBufferAllocator<128>;\ntemplate class SmallBufferAllocator<256>;\n\n} // namespace detail\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/small_buffer_allocator.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file small_buffer_allocator.h\n * @ingroup group_alloc\n * A file providing SmallBufferAllocator.  This allocator can allocate and deallocate chunks of a\n * set size in a way that is efficient and scales quite well across many threads.\n **/\n\n#pragma once\n\n#include <dispenso/detail/math.h>\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * Set a standard for the maximum chunk size for use within dispenso.  The reason for this limit is\n * that there are diminishing returns after a certain size, and each new pool has it's own memory\n * overhead.\n **/\nconstexpr size_t kMaxSmallBufferSize = 256;\n\nnamespace detail {\n\nDISPENSO_DLL_ACCESS char* allocSmallBufferImpl(size_t ordinal);\nDISPENSO_DLL_ACCESS void deallocSmallBufferImpl(size_t ordinal, void* buf);\n\nDISPENSO_DLL_ACCESS size_t approxBytesAllocatedSmallBufferImpl(size_t ordinal);\n\n// This has the effect of selecting actual block sizes starting with 4 bytes.  Smaller requests\n// (e.g. 1 byte, 2 bytes) will still utilize 4-byte blocks.  Choice of 4 bytes as the smallest\n// mainly aligns to sizeof(ptr) on 32-bit platforms, where we'd expect most common use cases to be\n// no smaller than one pointer.  Retaining 4-byte buckets on 64-bit platforms doesn't cost much\n// (tiny startup/teardown cost, and trivial amount of memory) when not using 4-byte or smaller\n// allocations, and makes the code simpler.\nconstexpr size_t getOrdinal(size_t blockSize) {\n  return static_cast<size_t>(std::max<ssize_t>(0, static_cast<ssize_t>(log2const(blockSize)) - 2));\n}\n\ntemplate <size_t kBlockSize>\ninline std::enable_if_t<(kBlockSize <= kMaxSmallBufferSize), char*> allocSmallOrLarge() {\n#if defined(DISPENSO_NO_SMALL_BUFFER_ALLOCATOR)\n  return reinterpret_cast<char*>(alignedMalloc(kBlockSize, kBlockSize));\n#else\n  return allocSmallBufferImpl(getOrdinal(kBlockSize));\n#endif // DISPENSO_NO_SMALL_BUFFER_ALLOCATOR\n}\n\ntemplate <size_t kBlockSize>\ninline std::enable_if_t<(kBlockSize > kMaxSmallBufferSize), char*> allocSmallOrLarge() {\n  return reinterpret_cast<char*>(alignedMalloc(kBlockSize, kBlockSize));\n}\n\ntemplate <size_t kBlockSize>\ninline std::enable_if_t<(kBlockSize <= kMaxSmallBufferSize), void> deallocSmallOrLarge(void* buf) {\n#if defined(DISPENSO_NO_SMALL_BUFFER_ALLOCATOR)\n  alignedFree(buf);\n#else\n  deallocSmallBufferImpl(getOrdinal(kBlockSize), buf);\n#endif // DISPENSO_NO_SMALL_BUFFER_ALLOCATOR\n}\n\ntemplate <size_t kBlockSize>\ninline std::enable_if_t<(kBlockSize > kMaxSmallBufferSize), void> deallocSmallOrLarge(void* buf) {\n  alignedFree(buf);\n}\n\n} // namespace detail\n\n/**\n * Allocate a small buffer from a small buffer pool.\n *\n * @tparam kBlockSize The size of the block to allocate.  Must be a power of two, and must be less\n * than or equal to kMaxSmallBufferSize.\n * @return The pointer to the allocated block of memory.\n * @note: The returned buffer must be returned to the pool via deallocSmallBuffer templatized on the\n * same block size.  If kBlockSize > kMaxSmallBufferSize, this function falls back on alignedMalloc.\n * If DISPENSO_NO_SMALL_BUFFER_ALLOCATOR is defined, we will always fall back on\n * alignedMalloc/alignedFree.\n **/\ntemplate <size_t kBlockSize>\ninline char* allocSmallBuffer() {\n  return detail::allocSmallOrLarge<kBlockSize>();\n}\n/**\n * Free a small buffer from a small buffer pool.\n *\n * @tparam kBlockSize The size of the block to allocate.  Must be a power of two, and must be less\n * than or equal to kMaxSmallBufferSize.\n * @param buf the pointer to block of memory to return to the pool.  Must have been allocated with\n * allocSmallBuffer templatized on the same block size.\n * @note: If kBlockSize > kMaxSmallBufferSize, this function falls back on alignedFree.\n **/\ntemplate <size_t kBlockSize>\ninline void deallocSmallBuffer(void* buf) {\n  detail::deallocSmallOrLarge<kBlockSize>(buf);\n}\n\n/**\n * Get the approximate bytes allocated for a single small buffer pool (associated with\n *kBlockSize). This function is not highly performant and locks, and should only be used for\n *diagnostics (e.g. tests).\n *\n * @tparam kBlockSize The block size for the pool to query.\n **/\ntemplate <size_t kBlockSize>\nsize_t approxBytesAllocatedSmallBuffer() {\n  return detail::approxBytesAllocatedSmallBufferImpl(detail::getOrdinal(kBlockSize));\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/small_vector.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file small_vector.h\n * @ingroup group_util\n * A vector-like container with inline storage for small sizes.\n *\n * SmallVector stores up to N elements inline (on the stack), falling back to\n * heap allocation when size exceeds N. Uses the high bit of the size field to\n * track storage mode, keeping the struct compact with no extra flags.\n *\n * Once transitioned to heap storage, the vector stays on heap until clear()\n * is called. This ensures reserve() guarantees are honored and avoids\n * unnecessary copies between storage modes.\n **/\n\n#pragma once\n\n#include <cassert>\n#include <cstddef>\n#include <initializer_list>\n#include <new>\n#include <utility>\n\nnamespace dispenso {\n\n/**\n * A vector-like container that stores up to N elements inline (on the stack),\n * avoiding heap allocation for small sizes. Falls back to heap allocation when\n * the size exceeds N.\n *\n * @tparam T The element type.\n * @tparam N The number of elements to store inline (default 4). Must be in range [1, 65535].\n *\n * Memory layout: Uses a union to share space between inline storage and heap\n * pointer/capacity. The high bit of the size field tracks whether heap storage\n * is active, so no additional bool or flag field is needed.\n *\n * Once on heap, the vector stays on heap until clear() is called. This ensures\n * reserve() capacity is preserved across push_back/pop_back sequences.\n */\ntemplate <typename T, size_t N = 4>\nclass SmallVector {\n  static_assert(N > 0, \"SmallVector requires at least 1 inline element. Use std::vector for N=0.\");\n  static_assert(N < 65536, \"SmallVector inline capacity is too large. Use std::vector instead.\");\n\n public:\n  using value_type = T;\n  using size_type = size_t;\n  using difference_type = std::ptrdiff_t;\n  using reference = T&;\n  using const_reference = const T&;\n  using pointer = T*;\n  using const_pointer = const T*;\n  using iterator = T*;\n  using const_iterator = const T*;\n\n  /**\n   * Construct an empty SmallVector.\n   **/\n  SmallVector() noexcept : size_(0) {}\n\n  /**\n   * Construct a SmallVector with @p count default-constructed elements.\n   *\n   * @param count The number of elements.\n   **/\n  explicit SmallVector(size_type count) : size_(0) {\n    resize(count);\n  }\n\n  /**\n   * Construct a SmallVector with @p count copies of @p value.\n   *\n   * @param count The number of elements.\n   * @param value The value to copy into each element.\n   **/\n  SmallVector(size_type count, const T& value) : size_(0) {\n    resize(count, value);\n  }\n\n  /**\n   * Construct a SmallVector from an initializer list.\n   *\n   * @param init The initializer list of elements.\n   **/\n  SmallVector(std::initializer_list<T> init) : size_(0) {\n    ensureCapacity(init.size());\n    for (const auto& v : init) {\n      emplace_back(v);\n    }\n  }\n\n  /** Copy constructor. **/\n  SmallVector(const SmallVector& other) : size_(0) {\n    ensureCapacity(other.rawSize());\n    for (const auto& v : other) {\n      emplace_back(v);\n    }\n  }\n\n  /** Move constructor. Moves elements and leaves @p other empty. **/\n  SmallVector(SmallVector&& other) noexcept : size_(0) {\n    if (other.isInline()) {\n      for (size_type i = 0; i < other.rawSize(); ++i) {\n        new (inlineData() + i) T(std::move(other.inlineData()[i]));\n        other.inlineData()[i].~T();\n      }\n    } else {\n      storage_.heap_.ptr = other.storage_.heap_.ptr;\n      storage_.heap_.capacity = other.storage_.heap_.capacity;\n      size_ |= kHeapBit;\n    }\n    size_ = (size_ & kHeapBit) | other.rawSize();\n    other.size_ = 0;\n  }\n\n  ~SmallVector() {\n    destroyAll();\n  }\n\n  /** Copy assignment operator. **/\n  SmallVector& operator=(const SmallVector& other) {\n    if (this != &other) {\n      destroyAll();\n      size_ = 0;\n      ensureCapacity(other.rawSize());\n      for (const auto& v : other) {\n        emplace_back(v);\n      }\n    }\n    return *this;\n  }\n\n  /** Move assignment operator. **/\n  SmallVector& operator=(SmallVector&& other) noexcept {\n    if (this != &other) {\n      destroyAll();\n      size_ = 0;\n\n      if (other.isInline()) {\n        for (size_type i = 0; i < other.rawSize(); ++i) {\n          new (inlineData() + i) T(std::move(other.inlineData()[i]));\n          other.inlineData()[i].~T();\n        }\n      } else {\n        storage_.heap_.ptr = other.storage_.heap_.ptr;\n        storage_.heap_.capacity = other.storage_.heap_.capacity;\n        size_ |= kHeapBit;\n      }\n      size_ = (size_ & kHeapBit) | other.rawSize();\n      other.size_ = 0;\n    }\n    return *this;\n  }\n\n  // --- Element Access ---\n\n  /** Access element at @p pos (unchecked). **/\n  reference operator[](size_type pos) {\n    return data()[pos];\n  }\n  /** @copydoc operator[](size_type) **/\n  const_reference operator[](size_type pos) const {\n    return data()[pos];\n  }\n  /** Access the first element. **/\n  reference front() {\n    return data()[0];\n  }\n  /** @copydoc front() **/\n  const_reference front() const {\n    return data()[0];\n  }\n  /** Access the last element. **/\n  reference back() {\n    return data()[rawSize() - 1];\n  }\n  /** @copydoc back() **/\n  const_reference back() const {\n    return data()[rawSize() - 1];\n  }\n\n  /** Return a pointer to the underlying element storage. **/\n  pointer data() noexcept {\n    return isInline() ? inlineData() : storage_.heap_.ptr;\n  }\n  /** @copydoc data() **/\n  const_pointer data() const noexcept {\n    return isInline() ? inlineData() : storage_.heap_.ptr;\n  }\n\n  // --- Iterators ---\n\n  /** Return an iterator to the first element. **/\n  iterator begin() noexcept {\n    return data();\n  }\n  /** @copydoc begin() **/\n  const_iterator begin() const noexcept {\n    return data();\n  }\n  /** @copydoc begin() **/\n  const_iterator cbegin() const noexcept {\n    return data();\n  }\n  /** Return an iterator past the last element. **/\n  iterator end() noexcept {\n    return data() + rawSize();\n  }\n  /** @copydoc end() **/\n  const_iterator end() const noexcept {\n    return data() + rawSize();\n  }\n  /** @copydoc end() **/\n  const_iterator cend() const noexcept {\n    return data() + rawSize();\n  }\n\n  // --- Capacity ---\n\n  /** Check whether the vector is empty. **/\n  bool empty() const noexcept {\n    return rawSize() == 0;\n  }\n  /** Return the number of elements. **/\n  size_type size() const noexcept {\n    return rawSize();\n  }\n\n  /**\n   * Return the current capacity.\n   * Returns N while using inline storage, or the heap capacity otherwise.\n   **/\n  size_type capacity() const noexcept {\n    return isInline() ? N : storage_.heap_.capacity;\n  }\n\n  /**\n   * Reserve capacity for at least newCap elements.\n   * If newCap > N, transitions to heap storage.\n   * Once on heap, capacity is preserved until clear().\n   */\n  void reserve(size_type newCap) {\n    ensureCapacity(newCap);\n  }\n\n  // --- Modifiers ---\n\n  /**\n   * Remove all elements and release heap storage (if any).\n   * After clear(), the vector returns to inline storage mode.\n   **/\n  void clear() noexcept {\n    destroyAll();\n    size_ = 0;\n  }\n\n  /** Append a copy of @p value. **/\n  void push_back(const T& value) {\n    emplace_back(value);\n  }\n  /** Append @p value by moving. **/\n  void push_back(T&& value) {\n    emplace_back(std::move(value));\n  }\n\n  /**\n   * Construct an element in-place at the end.\n   *\n   * @param args Arguments forwarded to the element constructor.\n   * @return A reference to the newly constructed element.\n   **/\n  template <typename... Args>\n  reference emplace_back(Args&&... args) {\n    T* ptr;\n    if (isInline()) {\n      size_type sz = rawSize();\n      if (sz < N) {\n        ptr = inlineData();\n      } else {\n        growToHeap(N * 2);\n        ptr = storage_.heap_.ptr;\n      }\n    } else {\n      size_type sz = rawSize();\n      if (sz == storage_.heap_.capacity) {\n        growToHeap(storage_.heap_.capacity * 2);\n      }\n      ptr = storage_.heap_.ptr;\n    }\n    size_type idx = rawSize();\n    new (ptr + idx) T(std::forward<Args>(args)...);\n    // Increment preserves heap bit naturally\n    ++size_;\n    assert(rawSize() > 0 && \"Size overflow into heap bit\");\n    return ptr[idx];\n  }\n\n  /** Remove the last element. **/\n  void pop_back() {\n    T* ptr = data();\n    size_type sz = rawSize();\n    ptr[sz - 1].~T();\n    // Decrement preserves heap bit naturally\n    --size_;\n  }\n\n  /**\n   * Resize the vector to @p count elements, default-constructing new elements if growing.\n   *\n   * @param count The desired number of elements.\n   **/\n  void resize(size_type count) {\n    size_type sz = rawSize();\n    if (count > sz) {\n      ensureCapacity(count);\n      T* ptr = data();\n      for (size_type i = sz; i < count; ++i) {\n        new (ptr + i) T();\n      }\n      setSize(count);\n    } else if (count < sz) {\n      T* ptr = data();\n      for (size_type i = count; i < sz; ++i) {\n        ptr[i].~T();\n      }\n      setSize(count);\n    }\n  }\n\n  /**\n   * Resize the vector to @p count elements, copy-constructing new elements from @p value if\n   * growing.\n   *\n   * @param count The desired number of elements.\n   * @param value The value to copy into new elements.\n   **/\n  void resize(size_type count, const T& value) {\n    size_type sz = rawSize();\n    if (count > sz) {\n      ensureCapacity(count);\n      T* ptr = data();\n      for (size_type i = sz; i < count; ++i) {\n        new (ptr + i) T(value);\n      }\n      setSize(count);\n    } else if (count < sz) {\n      T* ptr = data();\n      for (size_type i = count; i < sz; ++i) {\n        ptr[i].~T();\n      }\n      setSize(count);\n    }\n  }\n\n  /**\n   * Erase the element at @p pos.\n   * Elements after @p pos are shifted left. Returns an iterator to the element that now\n   * occupies the erased position (or end() if the last element was erased).\n   *\n   * @param pos Iterator to the element to erase.\n   * @return Iterator to the element following the erased one.\n   **/\n  iterator erase(const_iterator pos) {\n    T* ptr = data();\n    size_type sz = rawSize();\n    size_type index = pos - ptr;\n\n    for (size_type i = index; i + 1 < sz; ++i) {\n      ptr[i] = std::move(ptr[i + 1]);\n    }\n    ptr[sz - 1].~T();\n    --size_; // Preserves heap bit\n    return data() + index;\n  }\n\n private:\n  // High bit of size_ tracks heap vs inline mode.\n  // Since kHeapBit >> N, comparisons like size_ <= N and size_ < N\n  // are naturally false when the heap bit is set, so isInline() and\n  // many internal checks work without masking.\n  static constexpr size_type kHeapBit = size_type(1) << (sizeof(size_type) * 8 - 1);\n  static constexpr size_type kSizeMask = ~kHeapBit;\n\n  bool isInline() const noexcept {\n    return (size_ & kHeapBit) == 0;\n  }\n\n  size_type rawSize() const noexcept {\n    return size_ & kSizeMask;\n  }\n\n  // Set the size portion, preserving the heap bit.\n  void setSize(size_type s) noexcept {\n    assert((s & kHeapBit) == 0 && \"Size overflow into heap bit\");\n    size_ = (size_ & kHeapBit) | s;\n  }\n\n  T* inlineData() noexcept {\n    return reinterpret_cast<T*>(&storage_.inline_);\n  }\n  const T* inlineData() const noexcept {\n    return reinterpret_cast<const T*>(&storage_.inline_);\n  }\n\n  void destroyAll() noexcept {\n    T* ptr = data();\n    size_type sz = rawSize();\n    for (size_type i = 0; i < sz; ++i) {\n      ptr[i].~T();\n    }\n    if (!isInline()) {\n      ::operator delete(storage_.heap_.ptr);\n    }\n  }\n\n  // Grow to heap storage with the specified capacity.\n  // Moves existing elements, frees old heap if applicable, sets heap bit.\n  void growToHeap(size_type newCap) {\n    T* newData = static_cast<T*>(::operator new(newCap * sizeof(T)));\n    T* oldData = data();\n    size_type sz = rawSize();\n\n    for (size_type i = 0; i < sz; ++i) {\n      new (newData + i) T(std::move(oldData[i]));\n      oldData[i].~T();\n    }\n\n    if (!isInline()) {\n      ::operator delete(storage_.heap_.ptr);\n    }\n\n    storage_.heap_.ptr = newData;\n    storage_.heap_.capacity = newCap;\n    size_ = kHeapBit | sz;\n  }\n\n  void ensureCapacity(size_type newCap) {\n    if (newCap <= N && isInline()) {\n      return;\n    }\n    if (isInline()) {\n      growToHeap(newCap);\n    } else if (newCap > storage_.heap_.capacity) {\n      growToHeap(newCap);\n    }\n  }\n\n  size_type size_;\n\n  struct HeapStorage {\n    T* ptr;\n    size_type capacity;\n  };\n\n  union Storage {\n    alignas(T) unsigned char inline_[sizeof(T) * N];\n    HeapStorage heap_;\n    Storage() noexcept {}\n    ~Storage() {}\n  } storage_;\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/spsc_ring_buffer.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file spsc_ring_buffer.h\n * @ingroup group_util\n * A lock-free single-producer single-consumer (SPSC) ring buffer.\n *\n * This buffer is designed for high-performance communication between exactly one producer\n * thread and one consumer thread. It uses a fixed-capacity circular buffer with atomic\n * head and tail pointers, providing wait-free operations in the common case.\n *\n * @note This implementation is NOT thread-safe for multiple producers or multiple consumers.\n *       Use only with exactly one producer thread and one consumer thread.\n **/\n\n#pragma once\n\n#include <atomic>\n#include <cstddef>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include <dispenso/platform.h>\n#include <dispenso/util.h>\n\nnamespace dispenso {\n\n// TODO(bbudge): Add kDynamicCapacity specialization that heap-allocates storage\n// with runtime-determined capacity.\n\n/**\n * @class SPSCRingBuffer\n * @brief A lock-free single-producer single-consumer ring buffer with fixed capacity.\n *\n * This class implements a bounded, lock-free ring buffer optimized for the case where\n * there is exactly one producer thread and exactly one consumer thread. It uses relaxed\n * memory ordering where possible and acquire/release semantics only where necessary\n * for correctness.\n *\n * The buffer stores elements in a contiguous array, avoiding dynamic memory allocation\n * after construction. The capacity is fixed at compile time via a template parameter.\n *\n * Unlike std::array-based implementations, this buffer does NOT require the element type\n * to be default-constructible. Elements are constructed in-place when pushed and destroyed\n * when popped.\n *\n * @tparam T The type of elements stored in the buffer. Must be move-constructible.\n * @tparam Capacity The minimum number of elements the buffer can hold. Must be at least 1.\n *                  Defaults to 16, which provides good cache locality.\n * @tparam RoundUpToPowerOfTwo If true (default), rounds up the internal buffer size to the\n *                             next power of two for faster index wrap-around using bitwise\n *                             AND instead of modulo. This may result in actual capacity being\n *                             larger than requested. Set to false to use exactly the requested\n *                             capacity.\n *\n * ## Thread Safety\n *\n * This class is designed for exactly one producer thread and one consumer thread:\n * - Only one thread may call `try_push()` or `try_emplace()` at any time\n * - Only one thread may call `try_pop()` at any time\n * - The producer and consumer may be different threads\n * - `empty()`, `full()`, and `size()` may be called from any thread, but provide\n *   only a snapshot that may be immediately stale\n *\n * ## Memory Ordering\n *\n * The implementation uses:\n * - `memory_order_relaxed` for local reads of head/tail\n * - `memory_order_acquire` when reading the \"other\" index (consumer reads head, producer\n * reads tail)\n * - `memory_order_release` when updating head/tail after successful push/pop\n *\n * ## Performance Characteristics\n *\n * - Push: O(1), wait-free when buffer is not full\n * - Pop: O(1), wait-free when buffer is not empty\n * - Memory: sizeof(T) * (actual capacity + 1) + 2 cache lines for head/tail indices\n * - When RoundUpToPowerOfTwo is true (default), index wrap-around uses fast bitwise AND\n *\n * ## Example Usage\n *\n * @code\n * // Default: rounds up to power of two for performance\n * dispenso::SPSCRingBuffer<int, 100> buffer;  // actual capacity is 127 (128 - 1)\n *\n * // Exact capacity mode (no rounding)\n * dispenso::SPSCRingBuffer<int, 100, false> exact;  // actual capacity is 100\n *\n * // Producer thread\n * if (buffer.try_push(42)) {\n *     // Success\n * }\n *\n * // Consumer thread\n * int value;\n * if (buffer.try_pop(value)) {\n *     // Use value\n * }\n * @endcode\n *\n * @see https://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue\n *      for background on lock-free queue algorithms\n */\ntemplate <typename T, size_t Capacity = 16, bool RoundUpToPowerOfTwo = true>\nclass SPSCRingBuffer {\n  static_assert(Capacity >= 1, \"SPSCRingBuffer capacity must be at least 1\");\n  static_assert(\n      std::is_move_constructible<T>::value,\n      \"SPSCRingBuffer element type must be move-constructible\");\n\n public:\n  /**\n   * @brief The type of elements stored in this buffer.\n   */\n  using value_type = T;\n\n  /**\n   * @brief The size type used for indices and counts.\n   */\n  using size_type = size_t;\n\n  /**\n   * @brief Constructs an empty ring buffer.\n   *\n   * The buffer is initialized with no elements. The internal storage is\n   * uninitialized - elements are only constructed when pushed.\n   *\n   * @note Construction is not thread-safe. Ensure the buffer is fully\n   *       constructed before any thread accesses it.\n   */\n  SPSCRingBuffer() = default;\n\n  /**\n   * @brief Ring buffers are not copyable.\n   *\n   * Copying a concurrent data structure would require synchronization\n   * and could lead to subtle bugs. Use move semantics if you need to\n   * transfer ownership.\n   */\n  SPSCRingBuffer(const SPSCRingBuffer&) = delete;\n\n  /**\n   * @brief Ring buffers are not copy-assignable.\n   * @see SPSCRingBuffer(const SPSCRingBuffer&)\n   */\n  SPSCRingBuffer& operator=(const SPSCRingBuffer&) = delete;\n\n  /**\n   * @brief Ring buffers are not movable.\n   *\n   * Moving a ring buffer while producer/consumer threads are active\n   * would be unsafe. If you need to transfer ownership, ensure all\n   * threads have stopped first.\n   */\n  SPSCRingBuffer(SPSCRingBuffer&&) = delete;\n\n  /**\n   * @brief Ring buffers are not move-assignable.\n   * @see SPSCRingBuffer(SPSCRingBuffer&&)\n   */\n  SPSCRingBuffer& operator=(SPSCRingBuffer&&) = delete;\n\n  /**\n   * @brief Destroys the ring buffer.\n   *\n   * All elements remaining in the buffer are destroyed. Ensure no\n   * producer or consumer threads are accessing the buffer when it\n   * is destroyed.\n   *\n   * @note Destruction is not thread-safe.\n   */\n  ~SPSCRingBuffer() {\n    // Destroy any remaining elements\n    size_t head = head_.load(std::memory_order_relaxed);\n    size_t tail = tail_.load(std::memory_order_relaxed);\n    while (head != tail) {\n      elementAt(head)->~T();\n      head = increment(head);\n    }\n  }\n\n  /**\n   * @brief Attempts to push an element into the buffer by moving.\n   *\n   * If the buffer has space, the element is moved into the buffer and\n   * the function returns true. If the buffer is full, the function\n   * returns false and the element is unchanged.\n   *\n   * @param item The element to push (will be moved from on success).\n   * @return true if the element was successfully pushed, false if the buffer was full.\n   *\n   * @note Only one thread may call this function at any time (single producer).\n   * @note This operation is wait-free.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<std::string, 4> buffer;\n   * std::string msg = \"hello\";\n   * if (buffer.try_push(std::move(msg))) {\n   *     // msg is now empty (moved from)\n   * } else {\n   *     // msg is unchanged, buffer was full\n   * }\n   * @endcode\n   */\n  bool try_push(T&& item) {\n    const size_t currentTail = tail_.load(std::memory_order_relaxed);\n    const size_t nextTail = increment(currentTail);\n\n    // Check if buffer is full\n    if (nextTail == head_.load(std::memory_order_acquire)) {\n      return false;\n    }\n\n    // Construct element in-place\n    new (elementAt(currentTail)) T(std::move(item));\n    tail_.store(nextTail, std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * @brief Attempts to push an element into the buffer by copying.\n   *\n   * If the buffer has space, the element is copied into the buffer and\n   * the function returns true. If the buffer is full, the function\n   * returns false.\n   *\n   * @param item The element to push (will be copied).\n   * @return true if the element was successfully pushed, false if the buffer was full.\n   *\n   * @note Only one thread may call this function at any time (single producer).\n   * @note This operation is wait-free.\n   * @note Prefer try_push(T&&) when the source element is no longer needed.\n   */\n  bool try_push(const T& item) {\n    const size_t currentTail = tail_.load(std::memory_order_relaxed);\n    const size_t nextTail = increment(currentTail);\n\n    // Check if buffer is full\n    if (nextTail == head_.load(std::memory_order_acquire)) {\n      return false;\n    }\n\n    // Construct element in-place via copy\n    new (elementAt(currentTail)) T(item);\n    tail_.store(nextTail, std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * @brief Attempts to construct an element in-place in the buffer.\n   *\n   * If the buffer has space, constructs an element directly in the buffer\n   * storage using the provided arguments, avoiding any copy or move operations.\n   *\n   * @tparam Args The types of arguments to forward to T's constructor.\n   * @param args The arguments to forward to the element constructor.\n   * @return true if the element was successfully emplaced, false if the buffer was full.\n   *\n   * @note Only one thread may call this function at any time (single producer).\n   * @note This operation is wait-free.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<std::pair<int, std::string>, 4> buffer;\n   * if (buffer.try_emplace(42, \"hello\")) {\n   *     // Element constructed in-place\n   * }\n   * @endcode\n   */\n  template <typename... Args>\n  bool try_emplace(Args&&... args) {\n    const size_t currentTail = tail_.load(std::memory_order_relaxed);\n    const size_t nextTail = increment(currentTail);\n\n    // Check if buffer is full\n    if (nextTail == head_.load(std::memory_order_acquire)) {\n      return false;\n    }\n\n    // Construct element in-place\n    new (elementAt(currentTail)) T(std::forward<Args>(args)...);\n    tail_.store(nextTail, std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * @brief Attempts to pop an element from the buffer.\n   *\n   * If the buffer has elements, moves the front element into the output\n   * parameter and returns true. If the buffer is empty, returns false\n   * and leaves the output parameter unchanged.\n   *\n   * @param[out] item The location to move the popped element to.\n   * @return true if an element was successfully popped, false if the buffer was empty.\n   *\n   * @note Only one thread may call this function at any time (single consumer).\n   * @note This operation is wait-free.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<int, 4> buffer;\n   * buffer.try_push(42);\n   *\n   * int value;\n   * if (buffer.try_pop(value)) {\n   *     assert(value == 42);\n   * }\n   * @endcode\n   */\n  bool try_pop(T& item) {\n    const size_t currentHead = head_.load(std::memory_order_relaxed);\n\n    // Check if buffer is empty\n    if (currentHead == tail_.load(std::memory_order_acquire)) {\n      return false;\n    }\n\n    T* elem = elementAt(currentHead);\n    item = std::move(*elem);\n    elem->~T();\n    head_.store(increment(currentHead), std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * @brief Attempts to pop an element from the buffer, returning an optional.\n   *\n   * If the buffer has elements, moves the front element into an OpResult\n   * and returns it. If the buffer is empty, returns an empty OpResult.\n   *\n   * This provides a cleaner API than try_pop(T&) when default-constructibility\n   * of T is not guaranteed or when a more functional style is preferred.\n   *\n   * @return An OpResult containing the popped element, or an empty OpResult\n   *         if the buffer was empty.\n   *\n   * @note Only one thread may call this function at any time (single consumer).\n   * @note This operation is wait-free.\n   * @note In C++17 and beyond, you may prefer to use std::optional directly.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<std::string, 4> buffer;\n   * buffer.try_push(\"hello\");\n   *\n   * if (auto result = buffer.try_pop()) {\n   *     std::cout << result.value() << std::endl;\n   * }\n   * @endcode\n   */\n  OpResult<T> try_pop() {\n    const size_t currentHead = head_.load(std::memory_order_relaxed);\n\n    // Check if buffer is empty\n    if (currentHead == tail_.load(std::memory_order_acquire)) {\n      return {};\n    }\n\n    T* elem = elementAt(currentHead);\n    OpResult<T> result(std::move(*elem));\n    elem->~T();\n    head_.store(increment(currentHead), std::memory_order_release);\n    return result;\n  }\n\n  /**\n   * @brief Attempts to pop an element into uninitialized storage.\n   *\n   * Similar to try_pop, but uses placement new to construct the element\n   * into the provided storage. This is useful when T is not default-constructible.\n   *\n   * @param[out] storage Pointer to uninitialized storage where the element will be\n   *                     move-constructed. Must have proper alignment for T.\n   * @return true if an element was successfully popped, false if the buffer was empty.\n   *\n   * @note Only one thread may call this function at any time (single consumer).\n   * @note The caller is responsible for eventually destroying the constructed object.\n   * @note This operation is wait-free.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<NonDefaultConstructible, 4> buffer;\n   * alignas(NonDefaultConstructible) char storage[sizeof(NonDefaultConstructible)];\n   * if (buffer.try_pop_into(reinterpret_cast<NonDefaultConstructible*>(storage))) {\n   *     auto* ptr = reinterpret_cast<NonDefaultConstructible*>(storage);\n   *     // use *ptr\n   *     ptr->~NonDefaultConstructible();\n   * }\n   * @endcode\n   */\n  bool try_pop_into(T* storage) {\n    const size_t currentHead = head_.load(std::memory_order_relaxed);\n\n    // Check if buffer is empty\n    if (currentHead == tail_.load(std::memory_order_acquire)) {\n      return false;\n    }\n\n    T* elem = elementAt(currentHead);\n    new (storage) T(std::move(*elem));\n    elem->~T();\n    head_.store(increment(currentHead), std::memory_order_release);\n    return true;\n  }\n\n  /**\n   * @brief Attempts to push multiple elements into the buffer.\n   *\n   * Pushes as many elements as possible from the range [first, last) into the buffer\n   * in a single atomic tail update. This reduces atomic operation overhead when\n   * pushing multiple items.\n   *\n   * @tparam InputIt Input iterator type. Must dereference to a type convertible to T.\n   * @param first Iterator to the first element to push.\n   * @param last Iterator past the last element to push.\n   * @return The number of elements successfully pushed. May be less than the\n   *         range size if the buffer becomes full.\n   *\n   * @note Only one thread may call this function at any time (single producer).\n   * @note Elements are moved from the input range.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<int, 8> buffer;\n   * std::vector<int> items = {1, 2, 3, 4, 5};\n   * size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n   * // pushed contains the number of items successfully added\n   * @endcode\n   */\n  template <typename InputIt>\n  size_type try_push_batch(InputIt first, InputIt last) {\n    const size_t currentTail = tail_.load(std::memory_order_relaxed);\n    const size_t currentHead = head_.load(std::memory_order_acquire);\n\n    // Calculate available space (actual capacity is kBufferSize - 1)\n    size_t available;\n    if (currentTail >= currentHead) {\n      // Tail is ahead of or at head: available = capacity - (tail - head)\n      available = (kBufferSize - 1) - (currentTail - currentHead);\n    } else {\n      // Tail has wrapped: available = head - tail - 1\n      available = currentHead - currentTail - 1;\n    }\n\n    if (available == 0) {\n      return 0;\n    }\n\n    // Push as many items as possible\n    size_t count = 0;\n    size_t tailPos = currentTail;\n    for (; first != last && count < available; ++first, ++count) {\n      new (elementAt(tailPos)) T(std::move(*first));\n      tailPos = increment(tailPos);\n    }\n\n    if (count > 0) {\n      tail_.store(tailPos, std::memory_order_release);\n    }\n    return count;\n  }\n\n  /**\n   * @brief Attempts to pop multiple elements from the buffer.\n   *\n   * Pops up to maxCount elements from the buffer into the output iterator\n   * in a single atomic head update. This reduces atomic operation overhead\n   * when consuming multiple items.\n   *\n   * @tparam OutputIt Output iterator type. Must be assignable from T.\n   * @param dest Output iterator to write popped elements to.\n   * @param maxCount Maximum number of elements to pop.\n   * @return The number of elements successfully popped. May be less than\n   *         maxCount if the buffer has fewer elements.\n   *\n   * @note Only one thread may call this function at any time (single consumer).\n   * @note Elements are moved to the output range.\n   *\n   * ## Example\n   * @code\n   * SPSCRingBuffer<int, 8> buffer;\n   * // ... push some items ...\n   * std::vector<int> items(4);\n   * size_t popped = buffer.try_pop_batch(items.begin(), 4);\n   * // First 'popped' elements of items contain the popped values\n   * @endcode\n   */\n  template <typename OutputIt>\n  size_type try_pop_batch(OutputIt dest, size_type maxCount) {\n    const size_t currentHead = head_.load(std::memory_order_relaxed);\n    const size_t currentTail = tail_.load(std::memory_order_acquire);\n\n    // Calculate available items\n    size_t available;\n    if (currentTail >= currentHead) {\n      available = currentTail - currentHead;\n    } else {\n      available = kBufferSize - currentHead + currentTail;\n    }\n\n    if (available == 0) {\n      return 0;\n    }\n\n    // Pop as many items as requested and available\n    size_t count = std::min(available, maxCount);\n    size_t headPos = currentHead;\n    for (size_t i = 0; i < count; ++i, ++dest) {\n      T* elem = elementAt(headPos);\n      *dest = std::move(*elem);\n      elem->~T();\n      headPos = increment(headPos);\n    }\n\n    if (count > 0) {\n      head_.store(headPos, std::memory_order_release);\n    }\n    return count;\n  }\n\n  /**\n   * @brief Checks if the buffer is empty.\n   *\n   * @return true if the buffer contains no elements, false otherwise.\n   *\n   * @note This function provides only a snapshot of the buffer state.\n   *       The result may be stale by the time it is used, as another\n   *       thread may have pushed or popped an element.\n   *\n   * @note Safe to call from any thread, but the result is only a hint.\n   */\n  bool empty() const {\n    return head_.load(std::memory_order_acquire) == tail_.load(std::memory_order_acquire);\n  }\n\n  /**\n   * @brief Checks if the buffer is full.\n   *\n   * @return true if the buffer has no space for additional elements, false otherwise.\n   *\n   * @note This function provides only a snapshot of the buffer state.\n   *       The result may be stale by the time it is used, as another\n   *       thread may have popped an element.\n   *\n   * @note Safe to call from any thread, but the result is only a hint.\n   */\n  bool full() const {\n    return increment(tail_.load(std::memory_order_acquire)) ==\n        head_.load(std::memory_order_acquire);\n  }\n\n  /**\n   * @brief Returns the current number of elements in the buffer.\n   *\n   * @return The number of elements currently in the buffer.\n   *\n   * @note This function provides only a snapshot of the buffer state.\n   *       The result may be stale by the time it is used.\n   *\n   * @note Safe to call from any thread, but the result is only a hint.\n   *\n   * @note The implementation handles wrap-around correctly using modular\n   *       arithmetic.\n   */\n  size_type size() const {\n    const size_t head = head_.load(std::memory_order_acquire);\n    const size_t tail = tail_.load(std::memory_order_acquire);\n    // Handle wrap-around: if tail < head, we've wrapped\n    return (tail >= head) ? (tail - head) : (kBufferSize - head + tail);\n  }\n\n  /**\n   * @brief Returns the maximum number of elements the buffer can hold.\n   *\n   * When RoundUpToPowerOfTwo is true (default), this may be larger than the\n   * requested Capacity template parameter, as the internal buffer is rounded\n   * up to the next power of two for performance.\n   *\n   * @return The actual maximum capacity of the buffer (kBufferSize - 1).\n   *\n   * @note The actual storage uses capacity() + 1 slots internally to distinguish\n   *       between empty and full states.\n   */\n  static constexpr size_type capacity() noexcept {\n    return kBufferSize - 1;\n  }\n\n private:\n  /**\n   * @brief Computes the internal buffer size at compile time.\n   *\n   * When RoundUpToPowerOfTwo is true, rounds (Capacity + 1) up to the next power of two.\n   * Otherwise, uses exactly (Capacity + 1).\n   */\n  static constexpr size_t computeBufferSize() noexcept {\n    return RoundUpToPowerOfTwo ? static_cast<size_t>(detail::nextPow2(Capacity + 1)) : Capacity + 1;\n  }\n\n  /**\n   * @brief Internal buffer size (includes one extra slot to distinguish empty from full).\n   *\n   * The ring buffer uses one slot as a sentinel to distinguish between the\n   * empty state (head == tail) and the full state (next(tail) == head).\n   * When RoundUpToPowerOfTwo is true, this is rounded up to a power of two.\n   */\n  static constexpr size_t kBufferSize = computeBufferSize();\n\n  /**\n   * @brief Compile-time check if kBufferSize is a power of two.\n   *\n   * When true, we can use faster bitwise AND instead of modulo for wrap-around.\n   */\n  static constexpr bool kIsPowerOfTwo = (kBufferSize & (kBufferSize - 1)) == 0;\n\n  /**\n   * @brief Mask for power-of-two wrap-around (kBufferSize - 1).\n   *\n   * Only valid when kIsPowerOfTwo is true.\n   */\n  static constexpr size_t kMask = kBufferSize - 1;\n\n  /**\n   * @brief Increments an index with wrap-around.\n   *\n   * Uses bitwise AND when buffer size is a power of two (faster),\n   * otherwise falls back to modulo.\n   *\n   * @param index The current index.\n   * @return The next index, wrapping to 0 if necessary.\n   */\n  static constexpr size_t increment(size_t index) noexcept {\n    return kIsPowerOfTwo ? ((index + 1) & kMask) : ((index + 1) % kBufferSize);\n  }\n\n  /**\n   * @brief Returns a pointer to the element at the given index.\n   */\n  T* elementAt(size_t index) {\n    return reinterpret_cast<T*>(&storage_[index * sizeof(T)]);\n  }\n\n  const T* elementAt(size_t index) const {\n    return reinterpret_cast<const T*>(&storage_[index * sizeof(T)]);\n  }\n\n  /// Head index (consumer reads from here). Cache-line aligned to avoid false sharing.\n  alignas(kCacheLineSize) std::atomic<size_t> head_{0};\n\n  /// Tail index (producer writes here). Cache-line aligned to avoid false sharing.\n  alignas(kCacheLineSize) std::atomic<size_t> tail_{0};\n\n  /// Uninitialized storage for elements. Uses Capacity + 1 slots to distinguish empty from full.\n  /// Elements are constructed via placement new when pushed and explicitly destroyed when popped.\n  alignas(T) char storage_[sizeof(T) * kBufferSize];\n};\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/task_set.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"task_set.h\"\n\n#include <cstdio>\n\nnamespace dispenso {\n\nnamespace detail {\n// 64 depth is pretty ridiculous, but try not to step on anyone's feet.\nconstexpr int32_t kMaxTasksStackSize = 64;\n\nDISPENSO_THREAD_LOCAL TaskSetBase* g_taskStack[kMaxTasksStackSize];\nDISPENSO_THREAD_LOCAL int32_t g_taskStackSize = 0;\n\nvoid pushThreadTaskSet(TaskSetBase* t) {\n#ifndef NDEBUG\n  if (g_taskStackSize < 0 || g_taskStackSize >= kMaxTasksStackSize) {\n    fprintf(stderr, \"TaskSet parent stack index is invalid when pushing: %d\\n\", g_taskStackSize);\n    std::abort();\n  }\n#endif // NDEBUG\n  g_taskStack[g_taskStackSize++] = t;\n}\nvoid popThreadTaskSet() {\n#ifndef NDEBUG\n  if (g_taskStackSize <= 0) {\n    fprintf(stderr, \"TaskSet parent stack index is invalid when popping: %d\\n\", g_taskStackSize);\n    std::abort();\n  }\n#endif // NDEBUG\n  --g_taskStackSize;\n}\n} // namespace detail\n\nTaskSetBase* parentTaskSet() {\n  using namespace detail;\n\n#ifndef NDEBUG\n  if (g_taskStackSize < 0 || g_taskStackSize >= kMaxTasksStackSize) {\n    fprintf(stderr, \"TaskSet parent stack index is invalid when accessing: %d\\n\", g_taskStackSize);\n    std::abort();\n  }\n#endif // NDEBUG\n\n  return g_taskStackSize ? g_taskStack[g_taskStackSize - 1] : nullptr;\n}\n\nvoid TaskSetBase::trySetCurrentException() {\n#if defined(__cpp_exceptions)\n  auto status = kUnset;\n  if (guardException_.compare_exchange_strong(status, kSetting, std::memory_order_acq_rel)) {\n    exception_ = std::current_exception();\n    guardException_.store(kSet, std::memory_order_release);\n    canceled_.store(true, std::memory_order_release);\n  }\n#endif // __cpp_exceptions\n}\n\ninline bool TaskSetBase::testAndResetException() {\n#if defined(__cpp_exceptions)\n  if (guardException_.load(std::memory_order_acquire) == kSet) {\n    auto exception = std::move(exception_);\n    guardException_.store(kUnset, std::memory_order_release);\n    std::rethrow_exception(exception);\n  }\n#endif // __cpp_exceptions\n  return canceled_.load(std::memory_order_acquire);\n}\n\nbool ConcurrentTaskSet::wait() {\n  // Steal work until our set is unblocked.  Note that this is not the\n  // fastest possible way to unblock the current set, but it will alleviate\n  // deadlock, and should provide decent throughput for all waiters.\n\n  // The deadlock scenario mentioned goes as follows:  N threads in the\n  // ThreadPool.  Each thread is running code that is using TaskSets.  No\n  // progress could be made without stealing.\n  while (outstandingTaskCount_.load(std::memory_order_acquire)) {\n    if (!pool_.tryExecuteNext()) {\n      std::this_thread::yield();\n    }\n  }\n\n  return testAndResetException();\n}\n\nbool ConcurrentTaskSet::tryWait(size_t maxToExecute) {\n  while (outstandingTaskCount_.load(std::memory_order_acquire) && maxToExecute--) {\n    if (!pool_.tryExecuteNext()) {\n      break;\n    }\n  }\n\n  // Must check completion prior to checking exceptions, otherwise there could be a case where\n  // exceptions are checked, then an exception is propagated, and then we return whether all items\n  // have been completed, thus dropping the exception.\n  if (outstandingTaskCount_.load(std::memory_order_acquire)) {\n    return false;\n  }\n\n  return !testAndResetException();\n}\n\nmoodycamel::ProducerToken TaskSet::makeToken(moodycamel::ConcurrentQueue<OnceFunction>& pool) {\n  return moodycamel::ProducerToken(pool);\n}\n\nbool TaskSet::wait() {\n  // Steal work until our set is unblocked.\n  // The deadlock scenario mentioned goes as follows:  N threads in the\n  // ThreadPool.  Each thread is running code that is using TaskSets.  No\n  // progress could be made without stealing.\n  while (pool_.tryExecuteNextFromProducerToken(token_)) {\n  }\n\n  while (outstandingTaskCount_.load(std::memory_order_acquire)) {\n    if (!pool_.tryExecuteNext()) {\n      std::this_thread::yield();\n    }\n  }\n\n  return testAndResetException();\n}\n\nbool TaskSet::tryWait(size_t maxToExecute) {\n  ssize_t maxToExe = static_cast<ssize_t>(maxToExecute);\n  while (outstandingTaskCount_.load(std::memory_order_acquire) && maxToExe--) {\n    if (!pool_.tryExecuteNextFromProducerToken(token_)) {\n      break;\n    }\n  }\n\n  // Must check completion prior to checking exceptions, otherwise there could be a case where\n  // exceptions are checked, then an exception is propagated, and then we return whether all items\n  // have been completed, thus dropping the exception.\n\n  maxToExe = std::max<ssize_t>(0, maxToExe);\n\n  while (outstandingTaskCount_.load(std::memory_order_acquire) && maxToExe--) {\n    if (!pool_.tryExecuteNext()) {\n      std::this_thread::yield();\n    }\n  }\n\n  if (outstandingTaskCount_.load(std::memory_order_acquire)) {\n    return false;\n  }\n\n  return !testAndResetException();\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/task_set.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file task_set.h\n * @ingroup group_core\n * A file providing TaskSet and ConcurrentTaskSet.  These interfaces allow the user to\n * submit/schedule multiple closures and then wait on them.\n **/\n\n#pragma once\n\nnamespace dispenso {\nenum class ParentCascadeCancel { kOff, kOn };\n}\n\n#include <dispenso/detail/task_set_impl.h>\n\nnamespace dispenso {\n\nconstexpr ssize_t kDefaultStealingMultiplier = 4;\n\n/**\n * <code>TaskSet</code> is an object that allows scheduling multiple functors to a thread pool, and\n * allows to wait on that set of tasks.  <code>TaskSet</code> supplies more efficient schedule/wait\n * than <code>ConcurrentTaskSet</code>, but at the expense of only being usable from one thread at a\n * time.\n *\n * <code>TaskSet</code> is \"thread-compatible\".  This means that you can safely use\n * different <code>TaskSet</code> objects on different threads concurrently. Any given\n * <code>TaskSet</code> object may only be used from a single thread, so no concurrent use of that\n * object is allowed.\n **/\nclass TaskSet : public TaskSetBase {\n public:\n  /**\n   * Construct a TaskSet with the given backing pool.\n   *\n   * @param p The backing pool for this TaskSet\n   * @param registerForParentCancel Whether to register for parent cancellation cascade.\n   * @param stealingLoadMultiplier An over-load factor.  If this factor of load is reached by the\n   * underlying pool, scheduled tasks may run immediately in the calling thread.\n   **/\n  TaskSet(\n      ThreadPool& p,\n      ParentCascadeCancel registerForParentCancel,\n      ssize_t stealingLoadMultiplier = kDefaultStealingMultiplier)\n      : TaskSetBase(p, registerForParentCancel, stealingLoadMultiplier),\n        token_(makeToken(p.work_)) {}\n\n  /** Construct a TaskSet with default options. @param p The backing pool. */\n  TaskSet(ThreadPool& p) : TaskSet(p, ParentCascadeCancel::kOff, kDefaultStealingMultiplier) {}\n  /** Construct a TaskSet with custom load multiplier. @param p The backing pool. @param\n   * stealingLoadMultiplier The over-load factor. */\n  TaskSet(ThreadPool& p, ssize_t stealingLoadMultiplier)\n      : TaskSet(p, ParentCascadeCancel::kOff, stealingLoadMultiplier) {}\n\n  TaskSet(TaskSet&& other) = delete;\n  TaskSet& operator=(TaskSet&& other) = delete;\n\n  /**\n   * Schedule a functor for execution on the underlying pool.  If the load on the\n   * underlying pool is high, immediate inline execution may occur on the current thread.\n   *\n   * @param f A functor matching signature <code>void()</code>.  Best performance will come from\n   * passing lambdas, other concrete functors, or <code>OnceFunction</code>, but\n   * <code>std::function</code> or similarly type-erased objects will also work.\n   *\n   * @note If <code>f</code> can throw exceptions, then <code>schedule</code> may throw if the task\n   * is run inline.  Otherwise, exceptions will be caught on the running thread and best-effort\n   * propagated to the <code>ConcurrentTaskSet</code>, where the first one from the set is rethrown\n   * in <code>wait</code>.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f) {\n    if (DISPENSO_EXPECT(canceled(), false)) {\n      return;\n    }\n    if (outstandingTaskCount_.load(std::memory_order_relaxed) > taskSetLoadFactor_) {\n      f();\n    } else {\n      pool_.schedule(token_, packageTask(std::forward<F>(f)));\n    }\n  }\n\n  /**\n   * Schedule a functor for execution on the underlying pool.\n   *\n   * @param f A functor matching signature <code>void()</code>.  Best performance will come from\n   * passing lambdas, other concrete functors, or <code>OnceFunction</code>, but\n   * <code>std::function</code> or similarly type-erased objects will also work.\n   * @param fq Tag to force queuing instead of potential inline execution.\n   *\n   * @note If <code>f</code> can throw exceptions, then exceptions will be caught on the running\n   * thread and best-effort propagated to the <code>ConcurrentTaskSet</code>, where the first one\n   * from the set is rethrown in <code>wait</code>.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, ForceQueuingTag fq) {\n    pool_.schedule(token_, packageTask(std::forward<F>(f)), fq);\n  }\n\n  /**\n   * Schedule multiple functors for execution on the underlying pool in bulk.\n   * This is more efficient than calling schedule() multiple times when you have many tasks to\n   * submit, as it reduces atomic contention and allows for better thread wakeup behavior.\n   *\n   * @param count The number of functors to schedule.\n   * @param gen A generator functor that takes an index and returns a functor to execute.\n   *            gen(i) will be called for i in [0, count) to produce each task.\n   *\n   * @note Work is processed in chunks, interleaving enqueue and inline execution based on the\n   *       task set's load factor, preventing both pool thread starvation and excessive overhead.\n   **/\n  template <typename Generator>\n  void scheduleBulk(size_t count, Generator&& gen) {\n    scheduleBulkImpl(count, std::forward<Generator>(gen), &token_);\n  }\n\n  /**\n   * Wait for all currently scheduled functors to finish execution.  If exceptions are thrown\n   * during execution of the set of tasks, <code>wait</code> will propagate the first exception.\n   *\n   * @return true if the TaskSet was canceled, false otherwise\n   **/\n  DISPENSO_DLL_ACCESS bool wait();\n\n  /**\n   * See if the currently scheduled functors can be completed while stealing and executing at most\n   * <code>maxToExecute</code> of them from the pool. If not used in conjunction with wait, there\n   * may be cases that <code>tryWait</code> must be called multiple times with\n   * <code>maxToExecute &gt 0</code> to prevent livelock/deadlock.  If exceptions have been\n   * propagated since the last call to <code>wait</code> or <code>tryWait</code>,\n   * <code>tryWait</code> will propagate the first of them.\n   *\n   * @param maxToExecute The maximum number of tasks to proactively execute on the current thread.\n   *\n   * @return <code>true</code> if all currently scheduled functors have been completed prior to\n   * returning, and <code>false</code> otherwise.  This includes returning false if the TaskSet was\n   * cancelled.\n   **/\n  DISPENSO_DLL_ACCESS bool tryWait(size_t maxToExecute);\n\n  /**\n   * Set the TaskSet to canceled state.  No unexecuted tasks will execute once this is set.\n   * Already executing tasks may check canceled() status to exit early.\n   *\n   **/\n  void cancel() {\n    TaskSetBase::cancel();\n  }\n\n  /**\n   * Check the canceled status of the TaskSet.\n   *\n   * @return a boolean indicating whether or not the TaskSet has been canceled.\n   **/\n  bool canceled() const {\n    return TaskSetBase::canceled();\n  }\n\n  /**\n   * Destroy the TaskSet, first waiting for all currently scheduled functors to\n   * finish execution.\n   **/\n  ~TaskSet() {\n    wait();\n  }\n\n private:\n  DISPENSO_DLL_ACCESS moodycamel::ProducerToken makeToken(\n      moodycamel::ConcurrentQueue<OnceFunction>& pool);\n\n  moodycamel::ProducerToken token_;\n\n  template <typename Result>\n  friend class detail::FutureBase;\n};\n\n/**\n * <code>ConcurrentTaskSet</code> fulfills the same API as <code>TaskSet</code> with one minor\n * difference: It may be used to schedule tasks concurrently from multiple threads (see more below).\n * It is an object that allows scheduling multiple function-like objects to a thread pool, and\n * allows to wait on that set of tasks.\n *\n * <code>ConcurrentTaskSet</code> is \"thread-compatible\".  This means that you can safely use\n * different <code>ConcurrentTaskSet</code> objects on different threads concurrently.\n * <code>ConcurrentTaskSet</code> also allows multiple threads to concurrently schedule against it.\n * It is an error to call wait() concurrently with schedule() on the same\n * <code>ConcurrentTaskSet</code>.\n */\nclass ConcurrentTaskSet : public TaskSetBase {\n public:\n  /**\n   * Construct a ConcurrentTaskSet with the given backing pool.\n   *\n   * @param pool The backing pool for this ConcurrentTaskSet\n   * @param registerForParentCancel Whether to register for parent cancellation cascade.\n   * @param stealingLoadMultiplier An over-load factor.  If this factor of load is reached by the\n   * underlying pool, scheduled tasks may run immediately in the calling thread.\n   **/\n  ConcurrentTaskSet(\n      ThreadPool& pool,\n      ParentCascadeCancel registerForParentCancel,\n      ssize_t stealingLoadMultiplier = kDefaultStealingMultiplier)\n      : TaskSetBase(pool, registerForParentCancel, stealingLoadMultiplier) {}\n\n  /** Construct a ConcurrentTaskSet with default options. @param p The backing pool. */\n  ConcurrentTaskSet(ThreadPool& p)\n      : ConcurrentTaskSet(p, ParentCascadeCancel::kOff, kDefaultStealingMultiplier) {}\n  /** Construct a ConcurrentTaskSet with custom load multiplier. @param p The backing pool. @param\n   * stealingLoadMultiplier The over-load factor. */\n  ConcurrentTaskSet(ThreadPool& p, ssize_t stealingLoadMultiplier)\n      : ConcurrentTaskSet(p, ParentCascadeCancel::kOff, stealingLoadMultiplier) {}\n\n  ConcurrentTaskSet(ConcurrentTaskSet&& other) = delete;\n  ConcurrentTaskSet& operator=(ConcurrentTaskSet&& other) = delete;\n\n  /**\n   * Schedule a functor for execution on the underlying pool.  If the load on the\n   * underlying pool is high, immediate inline execution may occur on the current thread.\n   *\n   * @param f A functor matching signature <code>void()</code>.  Best performance will come from\n   * passing lambdas, other concrete functors, or <code>OnceFunction</code>, but\n   * <code>std::function</code> or similarly type-erased objects will also work.\n   *\n   * @param skipRecheck A poweruser knob that says that if we don't have enough outstanding tasks to\n   * immediately work steal, we should bypass the similar check in the ThreadPool.\n   *\n   * @note If <code>f</code> can throw exceptions, then <code>schedule</code> may throw if the task\n   * is run inline.  Otherwise, exceptions will be caught on the running thread and best-effort\n   * propagated to the <code>ConcurrentTaskSet</code>, where the first one from the set is rethrown\n   * in <code>wait</code>.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, bool skipRecheck = false) {\n    if (outstandingTaskCount_.load(std::memory_order_relaxed) > taskSetLoadFactor_ &&\n        DISPENSO_EXPECT(!canceled(), true)) {\n      f();\n    } else if (skipRecheck) {\n      pool_.schedule(packageTask(std::forward<F>(f)), ForceQueuingTag());\n    } else {\n      pool_.schedule(packageTask(std::forward<F>(f)));\n    }\n  }\n\n  /**\n   * Schedule a functor for execution on the underlying pool.\n   *\n   * @param f A functor matching signature <code>void()</code>.  Best performance will come from\n   * passing lambdas, other concrete functors, or <code>OnceFunction</code>, but\n   * <code>std::function</code> or similarly type-erased objects will also work.\n   * @param fq Tag to force queuing instead of potential inline execution.\n   *\n   * @note If <code>f</code> can throw exceptions, then exceptions will be caught on the running\n   * thread and best-effort propagated to the <code>ConcurrentTaskSet</code>, where the first one\n   * from the set is rethrown in <code>wait</code>.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, ForceQueuingTag fq) {\n    pool_.schedule(packageTask(std::forward<F>(f)), fq);\n  }\n\n  /**\n   * Schedule multiple functors for execution on the underlying pool in bulk.\n   * This is more efficient than calling schedule() multiple times when you have many tasks to\n   * submit, as it reduces atomic contention and allows for better thread wakeup behavior.\n   *\n   * @param count The number of functors to schedule.\n   * @param gen A generator functor that takes an index and returns a functor to execute.\n   *            gen(i) will be called for i in [0, count) to produce each task.\n   *\n   * @note Work is processed in chunks, interleaving enqueue and inline execution based on the\n   *       task set's load factor, preventing both pool thread starvation and excessive overhead.\n   **/\n  template <typename Generator>\n  void scheduleBulk(size_t count, Generator&& gen) {\n    scheduleBulkImpl(count, std::forward<Generator>(gen), nullptr);\n  }\n\n  /**\n   * Wait for all currently scheduled functors to finish execution.  If exceptions are thrown\n   * during execution of the set of tasks, <code>wait</code> will propagate the first exception.\n   **/\n  DISPENSO_DLL_ACCESS bool wait();\n\n  /**\n   * See if the currently scheduled functors can be completed while stealing and executing at most\n   * <code>maxToExecute</code> of them from the pool. If not used in conjunction with wait, there\n   * may be cases that <code>tryWait</code> must be called multiple times with\n   * <code>maxToExecute &gt 0</code> to prevent livelock/deadlock.  If exceptions have been\n   * propagated since the last call to <code>wait</code> or <code>tryWait</code>,\n   * <code>tryWait</code> will propagate the first of them.\n   *\n   * @param maxToExecute The maximum number of tasks to proactively execute on the current thread.\n   *\n   * @return <code>true</code> if all currently scheduled functors have been completed prior to\n   * returning, and <code>false</code> otherwise (including cancelled cases).\n   **/\n  DISPENSO_DLL_ACCESS bool tryWait(size_t maxToExecute);\n\n  /**\n   * Set the ConcurrentTaskSet to canceled state.  No unexecuted tasks will execute once this is\n   * set.  Already executing tasks may check canceled() status to exit early.\n   *\n   * @note This will be reset automatically by wait.\n   **/\n  void cancel() {\n    TaskSetBase::cancel();\n  }\n\n  /**\n   * Check the canceled status of the ConcurrentTaskSet.\n   *\n   * @return a boolean indicating whether or not the ConcurrentTaskSet has been canceled.\n   **/\n  bool canceled() const {\n    return TaskSetBase::canceled();\n  }\n\n  /**\n   * Destroy the ConcurrentTaskSet, first waiting for all currently scheduled functors to\n   * finish execution.\n   **/\n  ~ConcurrentTaskSet() {\n    wait();\n  }\n\n private:\n  bool tryExecuteNext() {\n    return pool_.tryExecuteNext();\n  }\n\n  template <typename Result>\n  friend class detail::FutureBase;\n\n  friend class detail::LimitGatedScheduler;\n};\n\n/**\n * Get access to the parent task set that scheduled the currently running code. nullptr if called\n * outside the context of a (Concurrent)TaskSet schedule.\n *\n **/\nDISPENSO_DLL_ACCESS TaskSetBase* parentTaskSet();\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/third-party/moodycamel/LICENSE.md",
    "content": "This license file applies to everything in this repository except that which\nis explicitly annotated as being written by other authors, i.e. the Boost\nqueue (included in the benchmarks for comparison), Intel's TBB library (ditto),\ndlib::pipe (ditto),\nthe CDSChecker tool (used for verification), the Relacy model checker (ditto),\nand Jeff Preshing's semaphore implementation (used in the blocking queue) which\nhas a zlib license (embedded in lightweightsempahore.h).\n\n---\n\nSimplified BSD License:\n\nCopyright (c) 2013-2016, Cameron Desrochers.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n- Redistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer.\n- Redistributions in binary form must reproduce the above copyright notice, this list of\nconditions and the following disclaimer in the documentation and/or other materials\nprovided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\nTHE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---\n\nI have also chosen to dual-license under the Boost Software License as an alternative to\nthe Simplified BSD license above:\n\nBoost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "dispenso/third-party/moodycamel/README.txt",
    "content": "https://github.com/cameron314/concurrentqueue\n\ncommit 65d6970912fc3f6bb62d80edf95ca30e0df85137 (HEAD -> master, origin/master, origin/HEAD)\nMerge: d49fa2b 08dcafc\nAuthor: Cameron <cameron@moodycamel.com>\nDate:   Sun Jul 24 10:02:12 2022 -0400\n\n    Merge pull request #308 from r8bhavneet/master\n    \n    Update README.md\n\ncommit 08dcafcd131b46e1a63abdc9b5f73c852193edca\nAuthor: r8bhavneet <98200254+r8bhavneet@users.noreply.github.com>\nDate:   Sun Jul 24 02:35:57 2022 -0700\n\n    Update README.md\n    \n    Hey, I really liked the project and was reading through the Readme.md file when I came across some redundant words and phrases which you might have missed whil\ne editing the documentation. It would be really a great opportunity for me if I could contribute to this project. Thank you.\n\ncommit d49fa2b0bd1c6185d93509f48c8987f9759d7238\nMerge: 0a40449 9dc1b2c\nAuthor: Cameron <cameron@moodycamel.com>\nDate:   Mon May 9 07:43:29 2022 -0400\n\n    Merge pull request #296 from MathiasMagnus/fix-c4554\n    \n    Proper MSVC warning fix and note\n\ncommit 9dc1b2cfcad03b4ee22ea57ddb5c453c41c19ac9\nAuthor: Máté Ferenc Nagy-Egri <mate@streamhpc.com>\nDate:   Mon May 9 13:19:39 2022 +0200\n\n    Proper MSVC warning fix and note\n\ncommit 0a404492ac2c0bba0f62eb2b859ec152e494f8bf\nAuthor: Cameron <cameron@moodycamel.com>\nDate:   Sat May 7 12:04:00 2022 -0400\n\n    Attempt to resolve -Wsign-conversion warnings in concurrentqueue.h (see #294)\n\ncommit 22c78daf65d2c8cce9399a29171676054aa98807\nMerge: c52e5ef 263c55d\nAuthor: Cameron <cameron@moodycamel.com>\nDate:   Sun Mar 20 15:16:30 2022 -0400\n\n    Merge pull request #290 from usurai/master\n    \n    Fix link in README\n\ncommit 263c55d5c95545abee1ef25662c752c5296d7c34\nAuthor: usurai <crowdwei@gmail.com>\nDate:   Thu Mar 17 16:09:14 2022 +0800\n\n    Fix link in README\n"
  },
  {
    "path": "dispenso/third-party/moodycamel/blockingconcurrentqueue.h",
    "content": "// Provides an efficient blocking version of moodycamel::ConcurrentQueue.\n// ©2015-2020 Cameron Desrochers. Distributed under the terms of the simplified\n// BSD license, available at the top of concurrentqueue.h.\n// Also dual-licensed under the Boost Software License (see LICENSE.md)\n// Uses Jeff Preshing's semaphore implementation (under the terms of its\n// separate zlib license, see lightweightsemaphore.h).\n\n#pragma once\n\n#include \"concurrentqueue.h\"\n#include \"lightweightsemaphore.h\"\n\n#include <type_traits>\n#include <cerrno>\n#include <memory>\n#include <chrono>\n#include <ctime>\n\nnamespace moodycamel\n{\n// This is a blocking version of the queue. It has an almost identical interface to\n// the normal non-blocking version, with the addition of various wait_dequeue() methods\n// and the removal of producer-specific dequeue methods.\ntemplate<typename T, typename Traits = ConcurrentQueueDefaultTraits>\nclass BlockingConcurrentQueue\n{\nprivate:\n\ttypedef ::moodycamel::ConcurrentQueue<T, Traits> ConcurrentQueue;\n\ttypedef ::moodycamel::LightweightSemaphore LightweightSemaphore;\n\npublic:\n\ttypedef typename ConcurrentQueue::producer_token_t producer_token_t;\n\ttypedef typename ConcurrentQueue::consumer_token_t consumer_token_t;\n\t\n\ttypedef typename ConcurrentQueue::index_t index_t;\n\ttypedef typename ConcurrentQueue::size_t size_t;\n\ttypedef typename std::make_signed<size_t>::type ssize_t;\n\t\n\tstatic const size_t BLOCK_SIZE = ConcurrentQueue::BLOCK_SIZE;\n\tstatic const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = ConcurrentQueue::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD;\n\tstatic const size_t EXPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::EXPLICIT_INITIAL_INDEX_SIZE;\n\tstatic const size_t IMPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::IMPLICIT_INITIAL_INDEX_SIZE;\n\tstatic const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = ConcurrentQueue::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;\n\tstatic const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = ConcurrentQueue::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE;\n\tstatic const size_t MAX_SUBQUEUE_SIZE = ConcurrentQueue::MAX_SUBQUEUE_SIZE;\n\t\npublic:\n\t// Creates a queue with at least `capacity` element slots; note that the\n\t// actual number of elements that can be inserted without additional memory\n\t// allocation depends on the number of producers and the block size (e.g. if\n\t// the block size is equal to `capacity`, only a single block will be allocated\n\t// up-front, which means only a single producer will be able to enqueue elements\n\t// without an extra allocation -- blocks aren't shared between producers).\n\t// This method is not thread safe -- it is up to the user to ensure that the\n\t// queue is fully constructed before it starts being used by other threads (this\n\t// includes making the memory effects of construction visible, possibly with a\n\t// memory barrier).\n\texplicit BlockingConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)\n\t\t: inner(capacity), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)\n\t{\n\t\tassert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && \"BlockingConcurrentQueue must have ConcurrentQueue as its first member\");\n\t\tif (!sema) {\n\t\t\tMOODYCAMEL_THROW(std::bad_alloc());\n\t\t}\n\t}\n\t\n\tBlockingConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)\n\t\t: inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)\n\t{\n\t\tassert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && \"BlockingConcurrentQueue must have ConcurrentQueue as its first member\");\n\t\tif (!sema) {\n\t\t\tMOODYCAMEL_THROW(std::bad_alloc());\n\t\t}\n\t}\n\t\n\t// Disable copying and copy assignment\n\tBlockingConcurrentQueue(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n\tBlockingConcurrentQueue& operator=(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\n\t// Moving is supported, but note that it is *not* a thread-safe operation.\n\t// Nobody can use the queue while it's being moved, and the memory effects\n\t// of that move must be propagated to other threads before they can use it.\n\t// Note: When a queue is moved, its tokens are still valid but can only be\n\t// used with the destination queue (i.e. semantically they are moved along\n\t// with the queue itself).\n\tBlockingConcurrentQueue(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n\t\t: inner(std::move(other.inner)), sema(std::move(other.sema))\n\t{ }\n\t\n\tinline BlockingConcurrentQueue& operator=(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\treturn swap_internal(other);\n\t}\n\t\n\t// Swaps this queue's state with the other's. Not thread-safe.\n\t// Swapping two queues does not invalidate their tokens, however\n\t// the tokens that were created for one queue must be used with\n\t// only the swapped queue (i.e. the tokens are tied to the\n\t// queue's movable state, not the object itself).\n\tinline void swap(BlockingConcurrentQueue& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tswap_internal(other);\n\t}\n\t\nprivate:\n\tBlockingConcurrentQueue& swap_internal(BlockingConcurrentQueue& other)\n\t{\n\t\tif (this == &other) {\n\t\t\treturn *this;\n\t\t}\n\t\t\n\t\tinner.swap(other.inner);\n\t\tsema.swap(other.sema);\n\t\treturn *this;\n\t}\n\t\npublic:\n\t// Enqueues a single item (by copying it).\n\t// Allocates memory if required. Only fails if memory allocation fails (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n\t// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(T const& item)\n\t{\n\t\tif ((details::likely)(inner.enqueue(item))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible).\n\t// Allocates memory if required. Only fails if memory allocation fails (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n\t// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(T&& item)\n\t{\n\t\tif ((details::likely)(inner.enqueue(std::move(item)))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by copying it) using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(producer_token_t const& token, T const& item)\n\t{\n\t\tif ((details::likely)(inner.enqueue(token, item))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible) using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(producer_token_t const& token, T&& item)\n\t{\n\t\tif ((details::likely)(inner.enqueue(token, std::move(item)))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues several items.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n\t// is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Note: Use std::make_move_iterator if the elements should be moved instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tinline bool enqueue_bulk(It itemFirst, size_t count)\n\t{\n\t\tif ((details::likely)(inner.enqueue_bulk(std::forward<It>(itemFirst), count))) {\n\t\t\tsema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues several items using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails\n\t// (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tinline bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n\t{\n\t\tif ((details::likely)(inner.enqueue_bulk(token, std::forward<It>(itemFirst), count))) {\n\t\t\tsema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by copying it).\n\t// Does not allocate memory. Fails if not enough room to enqueue (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n\t// is 0).\n\t// Thread-safe.\n\tinline bool try_enqueue(T const& item)\n\t{\n\t\tif (inner.try_enqueue(item)) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible).\n\t// Does not allocate memory (except for one-time implicit producer).\n\t// Fails if not enough room to enqueue (or implicit production is\n\t// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n\t// Thread-safe.\n\tinline bool try_enqueue(T&& item)\n\t{\n\t\tif (inner.try_enqueue(std::move(item))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by copying it) using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Thread-safe.\n\tinline bool try_enqueue(producer_token_t const& token, T const& item)\n\t{\n\t\tif (inner.try_enqueue(token, item)) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible) using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Thread-safe.\n\tinline bool try_enqueue(producer_token_t const& token, T&& item)\n\t{\n\t\tif (inner.try_enqueue(token, std::move(item))) {\n\t\t\tsema->signal();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues several items.\n\t// Does not allocate memory (except for one-time implicit producer).\n\t// Fails if not enough room to enqueue (or implicit production is\n\t// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tinline bool try_enqueue_bulk(It itemFirst, size_t count)\n\t{\n\t\tif (inner.try_enqueue_bulk(std::forward<It>(itemFirst), count)) {\n\t\t\tsema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Enqueues several items using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tinline bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n\t{\n\t\tif (inner.try_enqueue_bulk(token, std::forward<It>(itemFirst), count)) {\n\t\t\tsema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t\n\t// Attempts to dequeue from the queue.\n\t// Returns false if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline bool try_dequeue(U& item)\n\t{\n\t\tif (sema->tryWait()) {\n\t\t\twhile (!inner.try_dequeue(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Attempts to dequeue from the queue using an explicit consumer token.\n\t// Returns false if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline bool try_dequeue(consumer_token_t& token, U& item)\n\t{\n\t\tif (sema->tryWait()) {\n\t\t\twhile (!inner.try_dequeue(token, item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue.\n\t// Returns the number of items actually dequeued.\n\t// Returns 0 if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t try_dequeue_bulk(It itemFirst, size_t max)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue using an explicit consumer token.\n\t// Returns the number of items actually dequeued.\n\t// Returns 0 if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t\n\t\n\t// Blocks the current thread until there's something to dequeue, then\n\t// dequeues it.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline void wait_dequeue(U& item)\n\t{\n\t\twhile (!sema->wait()) {\n\t\t\tcontinue;\n\t\t}\n\t\twhile (!inner.try_dequeue(item)) {\n\t\t\tcontinue;\n\t\t}\n\t}\n\n\t// Blocks the current thread until either there's something to dequeue\n\t// or the timeout (specified in microseconds) expires. Returns false\n\t// without setting `item` if the timeout expires, otherwise assigns\n\t// to `item` and returns true.\n\t// Using a negative timeout indicates an indefinite timeout,\n\t// and is thus functionally equivalent to calling wait_dequeue.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline bool wait_dequeue_timed(U& item, std::int64_t timeout_usecs)\n\t{\n\t\tif (!sema->wait(timeout_usecs)) {\n\t\t\treturn false;\n\t\t}\n\t\twhile (!inner.try_dequeue(item)) {\n\t\t\tcontinue;\n\t\t}\n\t\treturn true;\n\t}\n    \n    // Blocks the current thread until either there's something to dequeue\n\t// or the timeout expires. Returns false without setting `item` if the\n    // timeout expires, otherwise assigns to `item` and returns true.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U, typename Rep, typename Period>\n\tinline bool wait_dequeue_timed(U& item, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return wait_dequeue_timed(item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());\n    }\n\t\n\t// Blocks the current thread until there's something to dequeue, then\n\t// dequeues it using an explicit consumer token.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline void wait_dequeue(consumer_token_t& token, U& item)\n\t{\n\t\twhile (!sema->wait()) {\n\t\t\tcontinue;\n\t\t}\n\t\twhile (!inner.try_dequeue(token, item)) {\n\t\t\tcontinue;\n\t\t}\n\t}\n\t\n\t// Blocks the current thread until either there's something to dequeue\n\t// or the timeout (specified in microseconds) expires. Returns false\n\t// without setting `item` if the timeout expires, otherwise assigns\n\t// to `item` and returns true.\n\t// Using a negative timeout indicates an indefinite timeout,\n\t// and is thus functionally equivalent to calling wait_dequeue.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::int64_t timeout_usecs)\n\t{\n\t\tif (!sema->wait(timeout_usecs)) {\n\t\t\treturn false;\n\t\t}\n\t\twhile (!inner.try_dequeue(token, item)) {\n\t\t\tcontinue;\n\t\t}\n\t\treturn true;\n\t}\n    \n    // Blocks the current thread until either there's something to dequeue\n\t// or the timeout expires. Returns false without setting `item` if the\n    // timeout expires, otherwise assigns to `item` and returns true.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U, typename Rep, typename Period>\n\tinline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return wait_dequeue_timed(token, item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());\n    }\n\t\n\t// Attempts to dequeue several elements from the queue.\n\t// Returns the number of items actually dequeued, which will\n\t// always be at least one (this method blocks until the queue\n\t// is non-empty) and at most max.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t wait_dequeue_bulk(It itemFirst, size_t max)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue.\n\t// Returns the number of items actually dequeued, which can\n\t// be 0 if the timeout expires while waiting for elements,\n\t// and at most max.\n\t// Using a negative timeout indicates an indefinite timeout,\n\t// and is thus functionally equivalent to calling wait_dequeue_bulk.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::int64_t timeout_usecs)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n    \n    // Attempts to dequeue several elements from the queue.\n\t// Returns the number of items actually dequeued, which can\n\t// be 0 if the timeout expires while waiting for elements,\n\t// and at most max.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It, typename Rep, typename Period>\n\tinline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return wait_dequeue_bulk_timed<It&>(itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());\n    }\n\t\n\t// Attempts to dequeue several elements from the queue using an explicit consumer token.\n\t// Returns the number of items actually dequeued, which will\n\t// always be at least one (this method blocks until the queue\n\t// is non-empty) and at most max.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t wait_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue using an explicit consumer token.\n\t// Returns the number of items actually dequeued, which can\n\t// be 0 if the timeout expires while waiting for elements,\n\t// and at most max.\n\t// Using a negative timeout indicates an indefinite timeout,\n\t// and is thus functionally equivalent to calling wait_dequeue_bulk.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::int64_t timeout_usecs)\n\t{\n\t\tsize_t count = 0;\n\t\tmax = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);\n\t\twhile (count != max) {\n\t\t\tcount += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue using an explicit consumer token.\n\t// Returns the number of items actually dequeued, which can\n\t// be 0 if the timeout expires while waiting for elements,\n\t// and at most max.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It, typename Rep, typename Period>\n\tinline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)\n    {\n        return wait_dequeue_bulk_timed<It&>(token, itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());\n    }\n\t\n\t\n\t// Returns an estimate of the total number of elements currently in the queue. This\n\t// estimate is only accurate if the queue has completely stabilized before it is called\n\t// (i.e. all enqueue and dequeue operations have completed and their memory effects are\n\t// visible on the calling thread, and no further operations start while this method is\n\t// being called).\n\t// Thread-safe.\n\tinline size_t size_approx() const\n\t{\n\t\treturn (size_t)sema->availableApprox();\n\t}\n\t\n\t\n\t// Returns true if the underlying atomic variables used by\n\t// the queue are lock-free (they should be on most platforms).\n\t// Thread-safe.\n\tstatic constexpr bool is_lock_free()\n\t{\n\t\treturn ConcurrentQueue::is_lock_free();\n\t}\n\t\n\nprivate:\n\ttemplate<typename U, typename A1, typename A2>\n\tstatic inline U* create(A1&& a1, A2&& a2)\n\t{\n\t\tvoid* p = (Traits::malloc)(sizeof(U));\n\t\treturn p != nullptr ? new (p) U(std::forward<A1>(a1), std::forward<A2>(a2)) : nullptr;\n\t}\n\t\n\ttemplate<typename U>\n\tstatic inline void destroy(U* p)\n\t{\n\t\tif (p != nullptr) {\n\t\t\tp->~U();\n\t\t}\n\t\t(Traits::free)(p);\n\t}\n\t\nprivate:\n\tConcurrentQueue inner;\n\tstd::unique_ptr<LightweightSemaphore, void (*)(LightweightSemaphore*)> sema;\n};\n\n\ntemplate<typename T, typename Traits>\ninline void swap(BlockingConcurrentQueue<T, Traits>& a, BlockingConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT\n{\n\ta.swap(b);\n}\n\n}\t// end namespace moodycamel\n"
  },
  {
    "path": "dispenso/third-party/moodycamel/concurrentqueue.h",
    "content": "// Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue.\n// An overview, including benchmark results, is provided here:\n//     http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++\n// The full design is also described in excruciating detail at:\n//    http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue\n\n// Simplified BSD license:\n// Copyright (c) 2013-2020, Cameron Desrochers.\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification,\n// are permitted provided that the following conditions are met:\n//\n// - Redistributions of source code must retain the above copyright notice, this list of\n// conditions and the following disclaimer.\n// - Redistributions in binary form must reproduce the above copyright notice, this list of\n// conditions and the following disclaimer in the documentation and/or other materials\n// provided with the distribution.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\n// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\n// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n// Also dual-licensed under the Boost Software License (see LICENSE.md)\n\n#pragma once\n\n#if defined(__GNUC__) && !defined(__INTEL_COMPILER)\n// Disable -Wconversion warnings (spuriously triggered when Traits::size_t and\n// Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings\n// upon assigning any computed values)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wconversion\"\n\n#if defined(__clang__)\n#pragma GCC diagnostic ignored \"-Wglobal-constructors\"\n#endif //__clang__\n\n#ifdef MCDBGQ_USE_RELACY\n#pragma GCC diagnostic ignored \"-Wint-to-pointer-cast\"\n#endif\n#endif\n\n#if defined(_MSC_VER) && (!defined(_HAS_CXX17) || !_HAS_CXX17)\n// VS2019 with /W4 warns about constant conditional expressions but unless /std=c++17 or higher\n// does not support `if constexpr`, so we have no choice but to simply disable the warning\n#pragma warning(push)\n#pragma warning(disable: 4127)  // conditional expression is constant\n#endif\n\n#if defined(__APPLE__)\n#include \"TargetConditionals.h\"\n#endif\n\n#ifdef MCDBGQ_USE_RELACY\n#include \"relacy/relacy_std.hpp\"\n#include \"relacy_shims.h\"\n// We only use malloc/free anyway, and the delete macro messes up `= delete` method declarations.\n// We'll override the default trait malloc ourselves without a macro.\n#undef new\n#undef delete\n#undef malloc\n#undef free\n#else\n#include <atomic>\t\t// Requires C++11. Sorry VS2010.\n#include <cassert>\n#endif\n#include <cstddef>              // for max_align_t\n#include <cstdint>\n#include <cstdlib>\n#include <type_traits>\n#include <algorithm>\n#include <utility>\n#include <limits>\n#include <climits>\t\t// for CHAR_BIT\n#include <array>\n#include <thread>\t\t// partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading\n#include <mutex>        // used for thread exit synchronization\n\n// Platform-specific definitions of a numeric thread ID type and an invalid value\nnamespace moodycamel { namespace details {\n\ttemplate<typename thread_id_t> struct thread_id_converter {\n\t\ttypedef thread_id_t thread_id_numeric_size_t;\n\t\ttypedef thread_id_t thread_id_hash_t;\n\t\tstatic thread_id_hash_t prehash(thread_id_t const& x) { return x; }\n\t};\n} }\n#if defined(MCDBGQ_USE_RELACY)\nnamespace moodycamel { namespace details {\n\ttypedef std::uint32_t thread_id_t;\n\tstatic const thread_id_t invalid_thread_id  = 0xFFFFFFFFU;\n\tstatic const thread_id_t invalid_thread_id2 = 0xFFFFFFFEU;\n\tstatic inline thread_id_t thread_id() { return rl::thread_index(); }\n} }\n#elif defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)\n// No sense pulling in windows.h in a header, we'll manually declare the function\n// we use and rely on backwards-compatibility for this not to break\nextern \"C\" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(void);\nnamespace moodycamel { namespace details {\n\tstatic_assert(sizeof(unsigned long) == sizeof(std::uint32_t), \"Expected size of unsigned long to be 32 bits on Windows\");\n\ttypedef std::uint32_t thread_id_t;\n\tstatic const thread_id_t invalid_thread_id  = 0;\t\t\t// See http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx\n\tstatic const thread_id_t invalid_thread_id2 = 0xFFFFFFFFU;\t// Not technically guaranteed to be invalid, but is never used in practice. Note that all Win32 thread IDs are presently multiples of 4.\n\tstatic inline thread_id_t thread_id() { return static_cast<thread_id_t>(::GetCurrentThreadId()); }\n} }\n#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE) || defined(MOODYCAMEL_NO_THREAD_LOCAL)\nnamespace moodycamel { namespace details {\n\tstatic_assert(sizeof(std::thread::id) == 4 || sizeof(std::thread::id) == 8, \"std::thread::id is expected to be either 4 or 8 bytes\");\n\t\n\ttypedef std::thread::id thread_id_t;\n\tstatic const thread_id_t invalid_thread_id;         // Default ctor creates invalid ID\n\n\t// Note we don't define a invalid_thread_id2 since std::thread::id doesn't have one; it's\n\t// only used if MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is defined anyway, which it won't\n\t// be.\n\tstatic inline thread_id_t thread_id() { return std::this_thread::get_id(); }\n\n\ttemplate<std::size_t> struct thread_id_size { };\n\ttemplate<> struct thread_id_size<4> { typedef std::uint32_t numeric_t; };\n\ttemplate<> struct thread_id_size<8> { typedef std::uint64_t numeric_t; };\n\n\ttemplate<> struct thread_id_converter<thread_id_t> {\n\t\ttypedef thread_id_size<sizeof(thread_id_t)>::numeric_t thread_id_numeric_size_t;\n#ifndef __APPLE__\n\t\ttypedef std::size_t thread_id_hash_t;\n#else\n\t\ttypedef thread_id_numeric_size_t thread_id_hash_t;\n#endif\n\n\t\tstatic thread_id_hash_t prehash(thread_id_t const& x)\n\t\t{\n#ifndef __APPLE__\n\t\t\treturn std::hash<std::thread::id>()(x);\n#else\n\t\t\treturn *reinterpret_cast<thread_id_hash_t const*>(&x);\n#endif\n\t\t}\n\t};\n} }\n#else\n// Use a nice trick from this answer: http://stackoverflow.com/a/8438730/21475\n// In order to get a numeric thread ID in a platform-independent way, we use a thread-local\n// static variable's address as a thread identifier :-)\n#if defined(__GNUC__) || defined(__INTEL_COMPILER)\n#define MOODYCAMEL_THREADLOCAL __thread\n#elif defined(_MSC_VER)\n#define MOODYCAMEL_THREADLOCAL __declspec(thread)\n#else\n// Assume C++11 compliant compiler\n#define MOODYCAMEL_THREADLOCAL thread_local\n#endif\nnamespace moodycamel { namespace details {\n\ttypedef std::uintptr_t thread_id_t;\n\tstatic const thread_id_t invalid_thread_id  = 0;\t\t// Address can't be nullptr\n\tstatic const thread_id_t invalid_thread_id2 = 1;\t\t// Member accesses off a null pointer are also generally invalid. Plus it's not aligned.\n\tinline thread_id_t thread_id() { static MOODYCAMEL_THREADLOCAL int x; return reinterpret_cast<thread_id_t>(&x); }\n} }\n#endif\n\n// Constexpr if\n#ifndef MOODYCAMEL_CONSTEXPR_IF\n#if (defined(_MSC_VER) && defined(_HAS_CXX17) && _HAS_CXX17) || __cplusplus > 201402L\n#define MOODYCAMEL_CONSTEXPR_IF if constexpr\n#define MOODYCAMEL_MAYBE_UNUSED [[maybe_unused]]\n#else\n#define MOODYCAMEL_CONSTEXPR_IF if\n#define MOODYCAMEL_MAYBE_UNUSED\n#endif\n#endif\n\n// Exceptions\n#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED\n#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__))\n#define MOODYCAMEL_EXCEPTIONS_ENABLED\n#endif\n#endif\n#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED\n#define MOODYCAMEL_TRY try\n#define MOODYCAMEL_CATCH(...) catch(__VA_ARGS__)\n#define MOODYCAMEL_RETHROW throw\n#define MOODYCAMEL_THROW(expr) throw (expr)\n#else\n#define MOODYCAMEL_TRY MOODYCAMEL_CONSTEXPR_IF (true)\n#define MOODYCAMEL_CATCH(...) else MOODYCAMEL_CONSTEXPR_IF (false)\n#define MOODYCAMEL_RETHROW\n#define MOODYCAMEL_THROW(expr)\n#endif\n\n#ifndef MOODYCAMEL_NOEXCEPT\n#if !defined(MOODYCAMEL_EXCEPTIONS_ENABLED)\n#define MOODYCAMEL_NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) true\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) true\n#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1800\n// VS2012's std::is_nothrow_[move_]constructible is broken and returns true when it shouldn't :-(\n// We have to assume *all* non-trivial constructors may throw on VS2012!\n#define MOODYCAMEL_NOEXCEPT _NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))\n#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1900\n#define MOODYCAMEL_NOEXCEPT _NOEXCEPT\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value || std::is_nothrow_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value || std::is_nothrow_copy_constructible<type>::value)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))\n#else\n#define MOODYCAMEL_NOEXCEPT noexcept\n#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) noexcept(expr)\n#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) noexcept(expr)\n#endif\n#endif\n\n#ifndef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#ifdef MCDBGQ_USE_RELACY\n#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#else\n// VS2013 doesn't support `thread_local`, and MinGW-w64 w/ POSIX threading has a crippling bug: http://sourceforge.net/p/mingw-w64/bugs/445\n// g++ <=4.7 doesn't support thread_local either.\n// Finally, iOS/ARM doesn't have support for it either, and g++/ARM allows it to compile but it's unconfirmed to actually work\n#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && (!defined(__MINGW32__) && !defined(__MINGW64__) || !defined(__WINPTHREADS_VERSION)) && (!defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && (!defined(__APPLE__) || !TARGET_OS_IPHONE) && !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)\n// Assume `thread_local` is fully supported in all other C++11 compilers/platforms\n#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED    // tentatively enabled for now; years ago several users report having problems with it on\n#endif\n#endif\n#endif\n\n// VS2012 doesn't support deleted functions. \n// In this case, we declare the function normally but don't define it. A link error will be generated if the function is called.\n#ifndef MOODYCAMEL_DELETE_FUNCTION\n#if defined(_MSC_VER) && _MSC_VER < 1800\n#define MOODYCAMEL_DELETE_FUNCTION\n#else\n#define MOODYCAMEL_DELETE_FUNCTION = delete\n#endif\n#endif\n\nnamespace moodycamel { namespace details {\n#ifndef MOODYCAMEL_ALIGNAS\n// VS2013 doesn't support alignas or alignof, and align() requires a constant literal\n#if defined(_MSC_VER) && _MSC_VER <= 1800\n#define MOODYCAMEL_ALIGNAS(alignment) __declspec(align(alignment))\n#define MOODYCAMEL_ALIGNOF(obj) __alignof(obj)\n#define MOODYCAMEL_ALIGNED_TYPE_LIKE(T, obj) typename details::Vs2013Aligned<std::alignment_of<obj>::value, T>::type\n\ttemplate<int Align, typename T> struct Vs2013Aligned { };  // default, unsupported alignment\n\ttemplate<typename T> struct Vs2013Aligned<1, T> { typedef __declspec(align(1)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<2, T> { typedef __declspec(align(2)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<4, T> { typedef __declspec(align(4)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<8, T> { typedef __declspec(align(8)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<16, T> { typedef __declspec(align(16)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<32, T> { typedef __declspec(align(32)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<64, T> { typedef __declspec(align(64)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<128, T> { typedef __declspec(align(128)) T type; };\n\ttemplate<typename T> struct Vs2013Aligned<256, T> { typedef __declspec(align(256)) T type; };\n#else\n\ttemplate<typename T> struct identity { typedef T type; };\n#define MOODYCAMEL_ALIGNAS(alignment) alignas(alignment)\n#define MOODYCAMEL_ALIGNOF(obj) alignof(obj)\n#define MOODYCAMEL_ALIGNED_TYPE_LIKE(T, obj) alignas(alignof(obj)) typename details::identity<T>::type\n#endif\n#endif\n} }\n\n\n// TSAN can false report races in lock-free code.  To enable TSAN to be used from projects that use this one,\n// we can apply per-function compile-time suppression.\n// See https://clang.llvm.org/docs/ThreadSanitizer.html#has-feature-thread-sanitizer\n#define MOODYCAMEL_NO_TSAN\n#if defined(__has_feature)\n #if __has_feature(thread_sanitizer)\n  #undef MOODYCAMEL_NO_TSAN\n  #define MOODYCAMEL_NO_TSAN __attribute__((no_sanitize(\"thread\")))\n #endif // TSAN\n#endif // TSAN\n\n// Compiler-specific likely/unlikely hints\nnamespace moodycamel { namespace details {\n#if defined(__GNUC__)\n\tstatic inline bool (likely)(bool x) { return __builtin_expect((x), true); }\n\tstatic inline bool (unlikely)(bool x) { return __builtin_expect((x), false); }\n#else\n\tstatic inline bool (likely)(bool x) { return x; }\n\tstatic inline bool (unlikely)(bool x) { return x; }\n#endif\n} }\n\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n#include \"internal/concurrentqueue_internal_debug.h\"\n#endif\n\nnamespace moodycamel {\nnamespace details {\n\ttemplate<typename T>\n\tstruct const_numeric_max {\n\t\tstatic_assert(std::is_integral<T>::value, \"const_numeric_max can only be used with integers\");\n\t\tstatic const T value = std::numeric_limits<T>::is_signed\n\t\t\t? (static_cast<T>(1) << (sizeof(T) * CHAR_BIT - 1)) - static_cast<T>(1)\n\t\t\t: static_cast<T>(-1);\n\t};\n\n#if defined(__GLIBCXX__)\n\ttypedef ::max_align_t std_max_align_t;      // libstdc++ forgot to add it to std:: for a while\n#else\n\ttypedef std::max_align_t std_max_align_t;   // Others (e.g. MSVC) insist it can *only* be accessed via std::\n#endif\n\n\t// Some platforms have incorrectly set max_align_t to a type with <8 bytes alignment even while supporting\n\t// 8-byte aligned scalar values (*cough* 32-bit iOS). Work around this with our own union. See issue #64.\n\ttypedef union {\n\t\tstd_max_align_t x;\n\t\tlong long y;\n\t\tvoid* z;\n\t} max_align_t;\n}\n\n// Default traits for the ConcurrentQueue. To change some of the\n// traits without re-implementing all of them, inherit from this\n// struct and shadow the declarations you wish to be different;\n// since the traits are used as a template type parameter, the\n// shadowed declarations will be used where defined, and the defaults\n// otherwise.\nstruct ConcurrentQueueDefaultTraits\n{\n\t// General-purpose size type. std::size_t is strongly recommended.\n\ttypedef std::size_t size_t;\n\t\n\t// The type used for the enqueue and dequeue indices. Must be at least as\n\t// large as size_t. Should be significantly larger than the number of elements\n\t// you expect to hold at once, especially if you have a high turnover rate;\n\t// for example, on 32-bit x86, if you expect to have over a hundred million\n\t// elements or pump several million elements through your queue in a very\n\t// short space of time, using a 32-bit type *may* trigger a race condition.\n\t// A 64-bit int type is recommended in that case, and in practice will\n\t// prevent a race condition no matter the usage of the queue. Note that\n\t// whether the queue is lock-free with a 64-int type depends on the whether\n\t// std::atomic<std::uint64_t> is lock-free, which is platform-specific.\n\ttypedef std::size_t index_t;\n\t\n\t// Internally, all elements are enqueued and dequeued from multi-element\n\t// blocks; this is the smallest controllable unit. If you expect few elements\n\t// but many producers, a smaller block size should be favoured. For few producers\n\t// and/or many elements, a larger block size is preferred. A sane default\n\t// is provided. Must be a power of 2.\n\tstatic const size_t BLOCK_SIZE = 32;\n\t\n\t// For explicit producers (i.e. when using a producer token), the block is\n\t// checked for being empty by iterating through a list of flags, one per element.\n\t// For large block sizes, this is too inefficient, and switching to an atomic\n\t// counter-based approach is faster. The switch is made for block sizes strictly\n\t// larger than this threshold.\n\tstatic const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = 32;\n\t\n\t// How many full blocks can be expected for a single explicit producer? This should\n\t// reflect that number's maximum for optimal performance. Must be a power of 2.\n\tstatic const size_t EXPLICIT_INITIAL_INDEX_SIZE = 32;\n\t\n\t// How many full blocks can be expected for a single implicit producer? This should\n\t// reflect that number's maximum for optimal performance. Must be a power of 2.\n\tstatic const size_t IMPLICIT_INITIAL_INDEX_SIZE = 32;\n\t\n\t// The initial size of the hash table mapping thread IDs to implicit producers.\n\t// Note that the hash is resized every time it becomes half full.\n\t// Must be a power of two, and either 0 or at least 1. If 0, implicit production\n\t// (using the enqueue methods without an explicit producer token) is disabled.\n\tstatic const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = 32;\n\t\n\t// Controls the number of items that an explicit consumer (i.e. one with a token)\n\t// must consume before it causes all consumers to rotate and move on to the next\n\t// internal queue.\n\tstatic const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = 256;\n\t\n\t// The maximum number of elements (inclusive) that can be enqueued to a sub-queue.\n\t// Enqueue operations that would cause this limit to be surpassed will fail. Note\n\t// that this limit is enforced at the block level (for performance reasons), i.e.\n\t// it's rounded up to the nearest block size.\n\tstatic const size_t MAX_SUBQUEUE_SIZE = details::const_numeric_max<size_t>::value;\n\n\t// The number of times to spin before sleeping when waiting on a semaphore.\n\t// Recommended values are on the order of 1000-10000 unless the number of\n\t// consumer threads exceeds the number of idle cores (in which case try 0-100).\n\t// Only affects instances of the BlockingConcurrentQueue.\n\tstatic const int MAX_SEMA_SPINS = 10000;\n\n\t// Whether to recycle dynamically-allocated blocks into an internal free list or\n\t// not. If false, only pre-allocated blocks (controlled by the constructor\n\t// arguments) will be recycled, and all others will be `free`d back to the heap.\n\t// Note that blocks consumed by explicit producers are only freed on destruction\n\t// of the queue (not following destruction of the token) regardless of this trait.\n\tstatic const bool RECYCLE_ALLOCATED_BLOCKS = false;\n\n\t\n#ifndef MCDBGQ_USE_RELACY\n\t// Memory allocation can be customized if needed.\n\t// malloc should return nullptr on failure, and handle alignment like std::malloc.\n#if defined(malloc) || defined(free)\n\t// Gah, this is 2015, stop defining macros that break standard code already!\n\t// Work around malloc/free being special macros:\n\tstatic inline void* WORKAROUND_malloc(size_t size) { return malloc(size); }\n\tstatic inline void WORKAROUND_free(void* ptr) { return free(ptr); }\n\tstatic inline void* (malloc)(size_t size) { return WORKAROUND_malloc(size); }\n\tstatic inline void (free)(void* ptr) { return WORKAROUND_free(ptr); }\n#else\n\tstatic inline void* malloc(size_t size) { return std::malloc(size); }\n\tstatic inline void free(void* ptr) { return std::free(ptr); }\n#endif\n#else\n\t// Debug versions when running under the Relacy race detector (ignore\n\t// these in user code)\n\tstatic inline void* malloc(size_t size) { return rl::rl_malloc(size, $); }\n\tstatic inline void free(void* ptr) { return rl::rl_free(ptr, $); }\n#endif\n};\n\n\n// When producing or consuming many elements, the most efficient way is to:\n//    1) Use one of the bulk-operation methods of the queue with a token\n//    2) Failing that, use the bulk-operation methods without a token\n//    3) Failing that, create a token and use that with the single-item methods\n//    4) Failing that, use the single-parameter methods of the queue\n// Having said that, don't create tokens willy-nilly -- ideally there should be\n// a maximum of one token per thread (of each kind).\nstruct ProducerToken;\nstruct ConsumerToken;\n\ntemplate<typename T, typename Traits> class ConcurrentQueue;\ntemplate<typename T, typename Traits> class BlockingConcurrentQueue;\nclass ConcurrentQueueTests;\n\n\nnamespace details\n{\n\tstruct ConcurrentQueueProducerTypelessBase\n\t{\n\t\tConcurrentQueueProducerTypelessBase* next;\n\t\tstd::atomic<bool> inactive;\n\t\tProducerToken* token;\n\t\t\n\t\tConcurrentQueueProducerTypelessBase()\n\t\t\t: next(nullptr), inactive(false), token(nullptr)\n\t\t{\n\t\t}\n\t};\n\t\n\ttemplate<bool use32> struct _hash_32_or_64 {\n\t\tstatic inline std::uint32_t hash(std::uint32_t h)\n\t\t{\n\t\t\t// MurmurHash3 finalizer -- see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp\n\t\t\t// Since the thread ID is already unique, all we really want to do is propagate that\n\t\t\t// uniqueness evenly across all the bits, so that we can use a subset of the bits while\n\t\t\t// reducing collisions significantly\n\t\t\th ^= h >> 16;\n\t\t\th *= 0x85ebca6b;\n\t\t\th ^= h >> 13;\n\t\t\th *= 0xc2b2ae35;\n\t\t\treturn h ^ (h >> 16);\n\t\t}\n\t};\n\ttemplate<> struct _hash_32_or_64<1> {\n\t\tstatic inline std::uint64_t hash(std::uint64_t h)\n\t\t{\n\t\t\th ^= h >> 33;\n\t\t\th *= 0xff51afd7ed558ccd;\n\t\t\th ^= h >> 33;\n\t\t\th *= 0xc4ceb9fe1a85ec53;\n\t\t\treturn h ^ (h >> 33);\n\t\t}\n\t};\n\ttemplate<std::size_t size> struct hash_32_or_64 : public _hash_32_or_64<(size > 4)> {  };\n\t\n\tstatic inline size_t hash_thread_id(thread_id_t id)\n\t{\n\t\tstatic_assert(sizeof(thread_id_t) <= 8, \"Expected a platform where thread IDs are at most 64-bit values\");\n\t\treturn static_cast<size_t>(hash_32_or_64<sizeof(thread_id_converter<thread_id_t>::thread_id_hash_t)>::hash(\n\t\t\tthread_id_converter<thread_id_t>::prehash(id)));\n\t}\n\t\n\ttemplate<typename T>\n\tstatic inline bool circular_less_than(T a, T b)\n\t{\n\t\tstatic_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, \"circular_less_than is intended to be used only with unsigned integer types\");\n\t\treturn static_cast<T>(a - b) > static_cast<T>(static_cast<T>(1) << (static_cast<T>(sizeof(T) * CHAR_BIT - 1)));\n\t\t// Note: extra parens around rhs of operator<< is MSVC bug: https://developercommunity2.visualstudio.com/t/C4554-triggers-when-both-lhs-and-rhs-is/10034931\n\t\t//       silencing the bug requires #pragma warning(disable: 4554) around the calling code and has no effect when done here.\n\t}\n\t\n\ttemplate<typename U>\n\tstatic inline char* align_for(char* ptr)\n\t{\n\t\tconst std::size_t alignment = std::alignment_of<U>::value;\n\t\treturn ptr + (alignment - (reinterpret_cast<std::uintptr_t>(ptr) % alignment)) % alignment;\n\t}\n\n\ttemplate<typename T>\n\tstatic inline T ceil_to_pow_2(T x)\n\t{\n\t\tstatic_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, \"ceil_to_pow_2 is intended to be used only with unsigned integer types\");\n\n\t\t// Adapted from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2\n\t\t--x;\n\t\tx |= x >> 1;\n\t\tx |= x >> 2;\n\t\tx |= x >> 4;\n\t\tfor (std::size_t i = 1; i < sizeof(T); i <<= 1) {\n\t\t\tx |= x >> (i << 3);\n\t\t}\n\t\t++x;\n\t\treturn x;\n\t}\n\t\n\ttemplate<typename T>\n\tstatic inline void swap_relaxed(std::atomic<T>& left, std::atomic<T>& right)\n\t{\n\t\tT temp = std::move(left.load(std::memory_order_relaxed));\n\t\tleft.store(std::move(right.load(std::memory_order_relaxed)), std::memory_order_relaxed);\n\t\tright.store(std::move(temp), std::memory_order_relaxed);\n\t}\n\t\n\ttemplate<typename T>\n\tstatic inline T const& nomove(T const& x)\n\t{\n\t\treturn x;\n\t}\n\t\n\ttemplate<bool Enable>\n\tstruct nomove_if\n\t{\n\t\ttemplate<typename T>\n\t\tstatic inline T const& eval(T const& x)\n\t\t{\n\t\t\treturn x;\n\t\t}\n\t};\n\t\n\ttemplate<>\n\tstruct nomove_if<false>\n\t{\n\t\ttemplate<typename U>\n\t\tstatic inline auto eval(U&& x)\n\t\t\t-> decltype(std::forward<U>(x))\n\t\t{\n\t\t\treturn std::forward<U>(x);\n\t\t}\n\t};\n\t\n\ttemplate<typename It>\n\tstatic inline auto deref_noexcept(It& it) MOODYCAMEL_NOEXCEPT -> decltype(*it)\n\t{\n\t\treturn *it;\n\t}\n\t\n#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)\n\ttemplate<typename T> struct is_trivially_destructible : std::is_trivially_destructible<T> { };\n#else\n\ttemplate<typename T> struct is_trivially_destructible : std::has_trivial_destructor<T> { };\n#endif\n\t\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n#ifdef MCDBGQ_USE_RELACY\n\ttypedef RelacyThreadExitListener ThreadExitListener;\n\ttypedef RelacyThreadExitNotifier ThreadExitNotifier;\n#else\n\tclass ThreadExitNotifier;\n\n\tstruct ThreadExitListener\n\t{\n\t\ttypedef void (*callback_t)(void*);\n\t\tcallback_t callback;\n\t\tvoid* userData;\n\t\t\n\t\tThreadExitListener* next;\t\t// reserved for use by the ThreadExitNotifier\n\t\tThreadExitNotifier* chain;\t\t// reserved for use by the ThreadExitNotifier\n\t};\n\n\tclass ThreadExitNotifier\n\t{\n\tpublic:\n\t\tstatic void subscribe(ThreadExitListener* listener)\n\t\t{\n\t\t\tauto& tlsInst = instance();\n\t\t\tstd::lock_guard<std::mutex> guard(mutex());\n\t\t\tlistener->next = tlsInst.tail;\n\t\t\tlistener->chain = &tlsInst;\n\t\t\ttlsInst.tail = listener;\n\t\t}\n\t\t\n\t\tstatic void unsubscribe(ThreadExitListener* listener)\n\t\t{\n\t\t\tstd::lock_guard<std::mutex> guard(mutex());\n\t\t\tif (!listener->chain) {\n\t\t\t\treturn;  // race with ~ThreadExitNotifier\n\t\t\t}\n\t\t\tauto& tlsInst = *listener->chain;\n\t\t\tlistener->chain = nullptr;\n\t\t\tThreadExitListener** prev = &tlsInst.tail;\n\t\t\tfor (auto ptr = tlsInst.tail; ptr != nullptr; ptr = ptr->next) {\n\t\t\t\tif (ptr == listener) {\n\t\t\t\t\t*prev = ptr->next;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tprev = &ptr->next;\n\t\t\t}\n\t\t}\n\t\t\n\tprivate:\n\t\tThreadExitNotifier() : tail(nullptr) { }\n\t\tThreadExitNotifier(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\tThreadExitNotifier& operator=(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\t\n\t\t~ThreadExitNotifier()\n\t\t{\n\t\t\t// This thread is about to exit, let everyone know!\n\t\t\tassert(this == &instance() && \"If this assert fails, you likely have a buggy compiler! Change the preprocessor conditions such that MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is no longer defined.\");\n\t\t\tstd::lock_guard<std::mutex> guard(mutex());\n\t\t\tfor (auto ptr = tail; ptr != nullptr; ptr = ptr->next) {\n\t\t\t\tptr->chain = nullptr;\n\t\t\t\tptr->callback(ptr->userData);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Thread-local\n\t\tstatic inline ThreadExitNotifier& instance()\n\t\t{\n\t\t\tstatic thread_local ThreadExitNotifier notifier;\n\t\t\treturn notifier;\n\t\t}\n\n\t\tstatic inline std::mutex& mutex()\n\t\t{\n\t\t\t// Must be static because the ThreadExitNotifier could be destroyed while unsubscribe is called\n\t\t\tstatic std::mutex mutex;\n\t\t\treturn mutex;\n\t\t}\n\t\t\n\tprivate:\n\t\tThreadExitListener* tail;\n\t};\n#endif\n#endif\n\t\n\ttemplate<typename T> struct static_is_lock_free_num { enum { value = 0 }; };\n\ttemplate<> struct static_is_lock_free_num<signed char> { enum { value = ATOMIC_CHAR_LOCK_FREE }; };\n\ttemplate<> struct static_is_lock_free_num<short> { enum { value = ATOMIC_SHORT_LOCK_FREE }; };\n\ttemplate<> struct static_is_lock_free_num<int> { enum { value = ATOMIC_INT_LOCK_FREE }; };\n\ttemplate<> struct static_is_lock_free_num<long> { enum { value = ATOMIC_LONG_LOCK_FREE }; };\n\ttemplate<> struct static_is_lock_free_num<long long> { enum { value = ATOMIC_LLONG_LOCK_FREE }; };\n\ttemplate<typename T> struct static_is_lock_free : static_is_lock_free_num<typename std::make_signed<T>::type> {  };\n\ttemplate<> struct static_is_lock_free<bool> { enum { value = ATOMIC_BOOL_LOCK_FREE }; };\n\ttemplate<typename U> struct static_is_lock_free<U*> { enum { value = ATOMIC_POINTER_LOCK_FREE }; };\n}\n\n\nstruct ProducerToken\n{\n\ttemplate<typename T, typename Traits>\n\texplicit ProducerToken(ConcurrentQueue<T, Traits>& queue);\n\t\n\ttemplate<typename T, typename Traits>\n\texplicit ProducerToken(BlockingConcurrentQueue<T, Traits>& queue);\n\t\n\tProducerToken(ProducerToken&& other) MOODYCAMEL_NOEXCEPT\n\t\t: producer(other.producer)\n\t{\n\t\tother.producer = nullptr;\n\t\tif (producer != nullptr) {\n\t\t\tproducer->token = this;\n\t\t}\n\t}\n\t\n\tinline ProducerToken& operator=(ProducerToken&& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tswap(other);\n\t\treturn *this;\n\t}\n\t\n\tvoid swap(ProducerToken& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tstd::swap(producer, other.producer);\n\t\tif (producer != nullptr) {\n\t\t\tproducer->token = this;\n\t\t}\n\t\tif (other.producer != nullptr) {\n\t\t\tother.producer->token = &other;\n\t\t}\n\t}\n\t\n\t// A token is always valid unless:\n\t//     1) Memory allocation failed during construction\n\t//     2) It was moved via the move constructor\n\t//        (Note: assignment does a swap, leaving both potentially valid)\n\t//     3) The associated queue was destroyed\n\t// Note that if valid() returns true, that only indicates\n\t// that the token is valid for use with a specific queue,\n\t// but not which one; that's up to the user to track.\n\tinline bool valid() const { return producer != nullptr; }\n\t\n\t~ProducerToken()\n\t{\n\t\tif (producer != nullptr) {\n\t\t\tproducer->token = nullptr;\n\t\t\tproducer->inactive.store(true, std::memory_order_release);\n\t\t}\n\t}\n\t\n\t// Disable copying and assignment\n\tProducerToken(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n\tProducerToken& operator=(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\nprivate:\n\ttemplate<typename T, typename Traits> friend class ConcurrentQueue;\n\tfriend class ConcurrentQueueTests;\n\t\nprotected:\n\tdetails::ConcurrentQueueProducerTypelessBase* producer;\n};\n\n\nstruct ConsumerToken\n{\n\ttemplate<typename T, typename Traits>\n\texplicit ConsumerToken(ConcurrentQueue<T, Traits>& q);\n\t\n\ttemplate<typename T, typename Traits>\n\texplicit ConsumerToken(BlockingConcurrentQueue<T, Traits>& q);\n\t\n\tConsumerToken(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT\n\t\t: initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer)\n\t{\n\t}\n\t\n\tinline ConsumerToken& operator=(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tswap(other);\n\t\treturn *this;\n\t}\n\t\n\tvoid swap(ConsumerToken& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tstd::swap(initialOffset, other.initialOffset);\n\t\tstd::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset);\n\t\tstd::swap(itemsConsumedFromCurrent, other.itemsConsumedFromCurrent);\n\t\tstd::swap(currentProducer, other.currentProducer);\n\t\tstd::swap(desiredProducer, other.desiredProducer);\n\t}\n\t\n\t// Disable copying and assignment\n\tConsumerToken(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n\tConsumerToken& operator=(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;\n\nprivate:\n\ttemplate<typename T, typename Traits> friend class ConcurrentQueue;\n\tfriend class ConcurrentQueueTests;\n\t\nprivate: // but shared with ConcurrentQueue\n\tstd::uint32_t initialOffset;\n\tstd::uint32_t lastKnownGlobalOffset;\n\tstd::uint32_t itemsConsumedFromCurrent;\n\tdetails::ConcurrentQueueProducerTypelessBase* currentProducer;\n\tdetails::ConcurrentQueueProducerTypelessBase* desiredProducer;\n};\n\n// Need to forward-declare this swap because it's in a namespace.\n// See http://stackoverflow.com/questions/4492062/why-does-a-c-friend-class-need-a-forward-declaration-only-in-other-namespaces\ntemplate<typename T, typename Traits>\ninline void swap(typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& a, typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT;\n\n\ntemplate<typename T, typename Traits = ConcurrentQueueDefaultTraits>\nclass ConcurrentQueue\n{\npublic:\n\ttypedef ::moodycamel::ProducerToken producer_token_t;\n\ttypedef ::moodycamel::ConsumerToken consumer_token_t;\n\t\n\ttypedef typename Traits::index_t index_t;\n\ttypedef typename Traits::size_t size_t;\n\t\n\tstatic const size_t BLOCK_SIZE = static_cast<size_t>(Traits::BLOCK_SIZE);\n\tstatic const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = static_cast<size_t>(Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD);\n\tstatic const size_t EXPLICIT_INITIAL_INDEX_SIZE = static_cast<size_t>(Traits::EXPLICIT_INITIAL_INDEX_SIZE);\n\tstatic const size_t IMPLICIT_INITIAL_INDEX_SIZE = static_cast<size_t>(Traits::IMPLICIT_INITIAL_INDEX_SIZE);\n\tstatic const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = static_cast<size_t>(Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE);\n\tstatic const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = static_cast<std::uint32_t>(Traits::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE);\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable: 4307)\t\t// + integral constant overflow (that's what the ternary expression is for!)\n#pragma warning(disable: 4309)\t\t// static_cast: Truncation of constant value\n#endif\n\tstatic const size_t MAX_SUBQUEUE_SIZE = (details::const_numeric_max<size_t>::value - static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) < BLOCK_SIZE) ? details::const_numeric_max<size_t>::value : ((static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE);\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n\tstatic_assert(!std::numeric_limits<size_t>::is_signed && std::is_integral<size_t>::value, \"Traits::size_t must be an unsigned integral type\");\n\tstatic_assert(!std::numeric_limits<index_t>::is_signed && std::is_integral<index_t>::value, \"Traits::index_t must be an unsigned integral type\");\n\tstatic_assert(sizeof(index_t) >= sizeof(size_t), \"Traits::index_t must be at least as wide as Traits::size_t\");\n\tstatic_assert((BLOCK_SIZE > 1) && !(BLOCK_SIZE & (BLOCK_SIZE - 1)), \"Traits::BLOCK_SIZE must be a power of 2 (and at least 2)\");\n\tstatic_assert((EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD > 1) && !(EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD & (EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD - 1)), \"Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD must be a power of 2 (and greater than 1)\");\n\tstatic_assert((EXPLICIT_INITIAL_INDEX_SIZE > 1) && !(EXPLICIT_INITIAL_INDEX_SIZE & (EXPLICIT_INITIAL_INDEX_SIZE - 1)), \"Traits::EXPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)\");\n\tstatic_assert((IMPLICIT_INITIAL_INDEX_SIZE > 1) && !(IMPLICIT_INITIAL_INDEX_SIZE & (IMPLICIT_INITIAL_INDEX_SIZE - 1)), \"Traits::IMPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)\");\n\tstatic_assert((INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) || !(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE & (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - 1)), \"Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be a power of 2\");\n\tstatic_assert(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0 || INITIAL_IMPLICIT_PRODUCER_HASH_SIZE >= 1, \"Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be at least 1 (or 0 to disable implicit enqueueing)\");\n\npublic:\n\t// Creates a queue with at least `capacity` element slots; note that the\n\t// actual number of elements that can be inserted without additional memory\n\t// allocation depends on the number of producers and the block size (e.g. if\n\t// the block size is equal to `capacity`, only a single block will be allocated\n\t// up-front, which means only a single producer will be able to enqueue elements\n\t// without an extra allocation -- blocks aren't shared between producers).\n\t// This method is not thread safe -- it is up to the user to ensure that the\n\t// queue is fully constructed before it starts being used by other threads (this\n\t// includes making the memory effects of construction visible, possibly with a\n\t// memory barrier).\n\texplicit ConcurrentQueue(size_t capacity = 32 * BLOCK_SIZE)\n\t\t: producerListTail(nullptr),\n\t\tproducerCount(0),\n\t\tinitialBlockPoolIndex(0),\n\t\tnextExplicitConsumerId(0),\n\t\tglobalExplicitConsumerOffset(0)\n\t{\n\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n\t\tpopulate_initial_implicit_producer_hash();\n\t\tpopulate_initial_block_list(capacity / BLOCK_SIZE + ((capacity & (BLOCK_SIZE - 1)) == 0 ? 0 : 1));\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\t\t// Track all the producers using a fully-resolved typed list for\n\t\t// each kind; this makes it possible to debug them starting from\n\t\t// the root queue object (otherwise wacky casts are needed that\n\t\t// don't compile in the debugger's expression evaluator).\n\t\texplicitProducers.store(nullptr, std::memory_order_relaxed);\n\t\timplicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n\t}\n\t\n\t// Computes the correct amount of pre-allocated blocks for you based\n\t// on the minimum number of elements you want available at any given\n\t// time, and the maximum concurrent number of each type of producer.\n\tConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)\n\t\t: producerListTail(nullptr),\n\t\tproducerCount(0),\n\t\tinitialBlockPoolIndex(0),\n\t\tnextExplicitConsumerId(0),\n\t\tglobalExplicitConsumerOffset(0)\n\t{\n\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n\t\tpopulate_initial_implicit_producer_hash();\n\t\tsize_t blocks = (((minCapacity + BLOCK_SIZE - 1) / BLOCK_SIZE) - 1) * (maxExplicitProducers + 1) + 2 * (maxExplicitProducers + maxImplicitProducers);\n\t\tpopulate_initial_block_list(blocks);\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\t\texplicitProducers.store(nullptr, std::memory_order_relaxed);\n\t\timplicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n\t}\n\t\n\t// Note: The queue should not be accessed concurrently while it's\n\t// being deleted. It's up to the user to synchronize this.\n\t// This method is not thread safe.\n\t~ConcurrentQueue()\n\t{\n\t\t// Destroy producers\n\t\tauto ptr = producerListTail.load(std::memory_order_relaxed);\n\t\twhile (ptr != nullptr) {\n\t\t\tauto next = ptr->next_prod();\n\t\t\tif (ptr->token != nullptr) {\n\t\t\t\tptr->token->producer = nullptr;\n\t\t\t}\n\t\t\tdestroy(ptr);\n\t\t\tptr = next;\n\t\t}\n\t\t\n\t\t// Destroy implicit producer hash tables\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE != 0) {\n\t\t\tauto hash = implicitProducerHash.load(std::memory_order_relaxed);\n\t\t\twhile (hash != nullptr) {\n\t\t\t\tauto prev = hash->prev;\n\t\t\t\tif (prev != nullptr) {\t\t// The last hash is part of this object and was not allocated dynamically\n\t\t\t\t\tfor (size_t i = 0; i != hash->capacity; ++i) {\n\t\t\t\t\t\thash->entries[i].~ImplicitProducerKVP();\n\t\t\t\t\t}\n\t\t\t\t\thash->~ImplicitProducerHash();\n\t\t\t\t\t(Traits::free)(hash);\n\t\t\t\t}\n\t\t\t\thash = prev;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Destroy global free list\n\t\tauto block = freeList.head_unsafe();\n\t\twhile (block != nullptr) {\n\t\t\tauto next = block->freeListNext.load(std::memory_order_relaxed);\n\t\t\tif (block->dynamicallyAllocated) {\n\t\t\t\tdestroy(block);\n\t\t\t}\n\t\t\tblock = next;\n\t\t}\n\t\t\n\t\t// Destroy initial free list\n\t\tdestroy_array(initialBlockPool, initialBlockPoolSize);\n\t}\n\n\t// Disable copying and copy assignment\n\tConcurrentQueue(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n\tConcurrentQueue& operator=(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\n\t// Moving is supported, but note that it is *not* a thread-safe operation.\n\t// Nobody can use the queue while it's being moved, and the memory effects\n\t// of that move must be propagated to other threads before they can use it.\n\t// Note: When a queue is moved, its tokens are still valid but can only be\n\t// used with the destination queue (i.e. semantically they are moved along\n\t// with the queue itself).\n\tConcurrentQueue(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n\t\t: producerListTail(other.producerListTail.load(std::memory_order_relaxed)),\n\t\tproducerCount(other.producerCount.load(std::memory_order_relaxed)),\n\t\tinitialBlockPoolIndex(other.initialBlockPoolIndex.load(std::memory_order_relaxed)),\n\t\tinitialBlockPool(other.initialBlockPool),\n\t\tinitialBlockPoolSize(other.initialBlockPoolSize),\n\t\tfreeList(std::move(other.freeList)),\n\t\tnextExplicitConsumerId(other.nextExplicitConsumerId.load(std::memory_order_relaxed)),\n\t\tglobalExplicitConsumerOffset(other.globalExplicitConsumerOffset.load(std::memory_order_relaxed))\n\t{\n\t\t// Move the other one into this, and leave the other one as an empty queue\n\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n\t\tpopulate_initial_implicit_producer_hash();\n\t\tswap_implicit_producer_hashes(other);\n\t\t\n\t\tother.producerListTail.store(nullptr, std::memory_order_relaxed);\n\t\tother.producerCount.store(0, std::memory_order_relaxed);\n\t\tother.nextExplicitConsumerId.store(0, std::memory_order_relaxed);\n\t\tother.globalExplicitConsumerOffset.store(0, std::memory_order_relaxed);\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\t\texplicitProducers.store(other.explicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed);\n\t\tother.explicitProducers.store(nullptr, std::memory_order_relaxed);\n\t\timplicitProducers.store(other.implicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed);\n\t\tother.implicitProducers.store(nullptr, std::memory_order_relaxed);\n#endif\n\t\t\n\t\tother.initialBlockPoolIndex.store(0, std::memory_order_relaxed);\n\t\tother.initialBlockPoolSize = 0;\n\t\tother.initialBlockPool = nullptr;\n\t\t\n\t\treown_producers();\n\t}\n\t\n\tinline ConcurrentQueue& operator=(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\treturn swap_internal(other);\n\t}\n\t\n\t// Swaps this queue's state with the other's. Not thread-safe.\n\t// Swapping two queues does not invalidate their tokens, however\n\t// the tokens that were created for one queue must be used with\n\t// only the swapped queue (i.e. the tokens are tied to the\n\t// queue's movable state, not the object itself).\n\tinline void swap(ConcurrentQueue& other) MOODYCAMEL_NOEXCEPT\n\t{\n\t\tswap_internal(other);\n\t}\n\t\nprivate:\n\tConcurrentQueue& swap_internal(ConcurrentQueue& other)\n\t{\n\t\tif (this == &other) {\n\t\t\treturn *this;\n\t\t}\n\t\t\n\t\tdetails::swap_relaxed(producerListTail, other.producerListTail);\n\t\tdetails::swap_relaxed(producerCount, other.producerCount);\n\t\tdetails::swap_relaxed(initialBlockPoolIndex, other.initialBlockPoolIndex);\n\t\tstd::swap(initialBlockPool, other.initialBlockPool);\n\t\tstd::swap(initialBlockPoolSize, other.initialBlockPoolSize);\n\t\tfreeList.swap(other.freeList);\n\t\tdetails::swap_relaxed(nextExplicitConsumerId, other.nextExplicitConsumerId);\n\t\tdetails::swap_relaxed(globalExplicitConsumerOffset, other.globalExplicitConsumerOffset);\n\t\t\n\t\tswap_implicit_producer_hashes(other);\n\t\t\n\t\treown_producers();\n\t\tother.reown_producers();\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\t\tdetails::swap_relaxed(explicitProducers, other.explicitProducers);\n\t\tdetails::swap_relaxed(implicitProducers, other.implicitProducers);\n#endif\n\t\t\n\t\treturn *this;\n\t}\n\t\npublic:\n\t// Enqueues a single item (by copying it).\n\t// Allocates memory if required. Only fails if memory allocation fails (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n\t// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(T const& item)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue<CanAlloc>(item);\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible).\n\t// Allocates memory if required. Only fails if memory allocation fails (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,\n\t// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(T&& item)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue<CanAlloc>(std::move(item));\n\t}\n\t\n\t// Enqueues a single item (by copying it) using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(producer_token_t const& token, T const& item)\n\t{\n\t\treturn inner_enqueue<CanAlloc>(token, item);\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible) using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Thread-safe.\n\tinline bool enqueue(producer_token_t const& token, T&& item)\n\t{\n\t\treturn inner_enqueue<CanAlloc>(token, std::move(item));\n\t}\n\t\n\t// Enqueues several items.\n\t// Allocates memory if required. Only fails if memory allocation fails (or\n\t// implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n\t// is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Note: Use std::make_move_iterator if the elements should be moved instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tbool enqueue_bulk(It itemFirst, size_t count)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue_bulk<CanAlloc>(itemFirst, count);\n\t}\n\t\n\t// Enqueues several items using an explicit producer token.\n\t// Allocates memory if required. Only fails if memory allocation fails\n\t// (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tbool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n\t{\n\t\treturn inner_enqueue_bulk<CanAlloc>(token, itemFirst, count);\n\t}\n\t\n\t// Enqueues a single item (by copying it).\n\t// Does not allocate memory. Fails if not enough room to enqueue (or implicit\n\t// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE\n\t// is 0).\n\t// Thread-safe.\n\tinline bool try_enqueue(T const& item)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue<CannotAlloc>(item);\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible).\n\t// Does not allocate memory (except for one-time implicit producer).\n\t// Fails if not enough room to enqueue (or implicit production is\n\t// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n\t// Thread-safe.\n\tinline bool try_enqueue(T&& item)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue<CannotAlloc>(std::move(item));\n\t}\n\t\n\t// Enqueues a single item (by copying it) using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Thread-safe.\n\tinline bool try_enqueue(producer_token_t const& token, T const& item)\n\t{\n\t\treturn inner_enqueue<CannotAlloc>(token, item);\n\t}\n\t\n\t// Enqueues a single item (by moving it, if possible) using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Thread-safe.\n\tinline bool try_enqueue(producer_token_t const& token, T&& item)\n\t{\n\t\treturn inner_enqueue<CannotAlloc>(token, std::move(item));\n\t}\n\t\n\t// Enqueues several items.\n\t// Does not allocate memory (except for one-time implicit producer).\n\t// Fails if not enough room to enqueue (or implicit production is\n\t// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tbool try_enqueue_bulk(It itemFirst, size_t count)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false;\n\t\telse return inner_enqueue_bulk<CannotAlloc>(itemFirst, count);\n\t}\n\t\n\t// Enqueues several items using an explicit producer token.\n\t// Does not allocate memory. Fails if not enough room to enqueue.\n\t// Note: Use std::make_move_iterator if the elements should be moved\n\t// instead of copied.\n\t// Thread-safe.\n\ttemplate<typename It>\n\tbool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n\t{\n\t\treturn inner_enqueue_bulk<CannotAlloc>(token, itemFirst, count);\n\t}\n\t\n\t\n\t\n\t// Attempts to dequeue from the queue.\n\t// Returns false if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tbool try_dequeue(U& item)\n\t{\n\t\t// Instead of simply trying each producer in turn (which could cause needless contention on the first\n\t\t// producer), we score them heuristically.\n\t\tsize_t nonEmptyCount = 0;\n\t\tProducerBase* best = nullptr;\n\t\tsize_t bestSize = 0;\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); nonEmptyCount < 3 && ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tauto size = ptr->size_approx();\n\t\t\tif (size > 0) {\n\t\t\t\tif (size > bestSize) {\n\t\t\t\t\tbestSize = size;\n\t\t\t\t\tbest = ptr;\n\t\t\t\t}\n\t\t\t\t++nonEmptyCount;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// If there was at least one non-empty queue but it appears empty at the time\n\t\t// we try to dequeue from it, we need to make sure every queue's been tried\n\t\tif (nonEmptyCount > 0) {\n\t\t\tif ((details::likely)(best->dequeue(item))) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\t\tif (ptr != best && ptr->dequeue(item)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Attempts to dequeue from the queue.\n\t// Returns false if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// This differs from the try_dequeue(item) method in that this one does\n\t// not attempt to reduce contention by interleaving the order that producer\n\t// streams are dequeued from. So, using this method can reduce overall throughput\n\t// under contention, but will give more predictable results in single-threaded\n\t// consumer scenarios. This is mostly only useful for internal unit tests.\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tbool try_dequeue_non_interleaved(U& item)\n\t{\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tif (ptr->dequeue(item)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Attempts to dequeue from the queue using an explicit consumer token.\n\t// Returns false if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tbool try_dequeue(consumer_token_t& token, U& item)\n\t{\n\t\t// The idea is roughly as follows:\n\t\t// Every 256 items from one producer, make everyone rotate (increase the global offset) -> this means the highest efficiency consumer dictates the rotation speed of everyone else, more or less\n\t\t// If you see that the global offset has changed, you must reset your consumption counter and move to your designated place\n\t\t// If there's no items where you're supposed to be, keep moving until you find a producer with some items\n\t\t// If the global offset has not changed but you've run out of items to consume, move over from your current position until you find an producer with something in it\n\t\t\n\t\tif (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) {\n\t\t\tif (!update_current_producer_after_rotation(token)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// If there was at least one non-empty queue but it appears empty at the time\n\t\t// we try to dequeue from it, we need to make sure every queue's been tried\n\t\tif (static_cast<ProducerBase*>(token.currentProducer)->dequeue(item)) {\n\t\t\tif (++token.itemsConsumedFromCurrent == EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) {\n\t\t\t\tglobalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tauto tail = producerListTail.load(std::memory_order_acquire);\n\t\tauto ptr = static_cast<ProducerBase*>(token.currentProducer)->next_prod();\n\t\tif (ptr == nullptr) {\n\t\t\tptr = tail;\n\t\t}\n\t\twhile (ptr != static_cast<ProducerBase*>(token.currentProducer)) {\n\t\t\tif (ptr->dequeue(item)) {\n\t\t\t\ttoken.currentProducer = ptr;\n\t\t\t\ttoken.itemsConsumedFromCurrent = 1;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tptr = ptr->next_prod();\n\t\t\tif (ptr == nullptr) {\n\t\t\t\tptr = tail;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue.\n\t// Returns the number of items actually dequeued.\n\t// Returns 0 if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tsize_t try_dequeue_bulk(It itemFirst, size_t max)\n\t{\n\t\tsize_t count = 0;\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tcount += ptr->dequeue_bulk(itemFirst, max - count);\n\t\t\tif (count == max) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t// Attempts to dequeue several elements from the queue using an explicit consumer token.\n\t// Returns the number of items actually dequeued.\n\t// Returns 0 if all producer streams appeared empty at the time they\n\t// were checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tsize_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)\n\t{\n\t\tif (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) {\n\t\t\tif (!update_current_producer_after_rotation(token)) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\t\n\t\tsize_t count = static_cast<ProducerBase*>(token.currentProducer)->dequeue_bulk(itemFirst, max);\n\t\tif (count == max) {\n\t\t\tif ((token.itemsConsumedFromCurrent += static_cast<std::uint32_t>(max)) >= EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) {\n\t\t\t\tglobalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed);\n\t\t\t}\n\t\t\treturn max;\n\t\t}\n\t\ttoken.itemsConsumedFromCurrent += static_cast<std::uint32_t>(count);\n\t\tmax -= count;\n\t\t\n\t\tauto tail = producerListTail.load(std::memory_order_acquire);\n\t\tauto ptr = static_cast<ProducerBase*>(token.currentProducer)->next_prod();\n\t\tif (ptr == nullptr) {\n\t\t\tptr = tail;\n\t\t}\n\t\twhile (ptr != static_cast<ProducerBase*>(token.currentProducer)) {\n\t\t\tauto dequeued = ptr->dequeue_bulk(itemFirst, max);\n\t\t\tcount += dequeued;\n\t\t\tif (dequeued != 0) {\n\t\t\t\ttoken.currentProducer = ptr;\n\t\t\t\ttoken.itemsConsumedFromCurrent = static_cast<std::uint32_t>(dequeued);\n\t\t\t}\n\t\t\tif (dequeued == max) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmax -= dequeued;\n\t\t\tptr = ptr->next_prod();\n\t\t\tif (ptr == nullptr) {\n\t\t\t\tptr = tail;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\t\n\t\n\t\n\t// Attempts to dequeue from a specific producer's inner queue.\n\t// If you happen to know which producer you want to dequeue from, this\n\t// is significantly faster than using the general-case try_dequeue methods.\n\t// Returns false if the producer's queue appeared empty at the time it\n\t// was checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename U>\n\tinline bool try_dequeue_from_producer(producer_token_t const& producer, U& item)\n\t{\n\t\treturn static_cast<ExplicitProducer*>(producer.producer)->dequeue(item);\n\t}\n\t\n\t// Attempts to dequeue several elements from a specific producer's inner queue.\n\t// Returns the number of items actually dequeued.\n\t// If you happen to know which producer you want to dequeue from, this\n\t// is significantly faster than using the general-case try_dequeue methods.\n\t// Returns 0 if the producer's queue appeared empty at the time it\n\t// was checked (so, the queue is likely but not guaranteed to be empty).\n\t// Never allocates. Thread-safe.\n\ttemplate<typename It>\n\tinline size_t try_dequeue_bulk_from_producer(producer_token_t const& producer, It itemFirst, size_t max)\n\t{\n\t\treturn static_cast<ExplicitProducer*>(producer.producer)->dequeue_bulk(itemFirst, max);\n\t}\n\t\n\t\n\t// Returns an estimate of the total number of elements currently in the queue. This\n\t// estimate is only accurate if the queue has completely stabilized before it is called\n\t// (i.e. all enqueue and dequeue operations have completed and their memory effects are\n\t// visible on the calling thread, and no further operations start while this method is\n\t// being called).\n\t// Thread-safe.\n\tsize_t size_approx() const\n\t{\n\t\tsize_t size = 0;\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tsize += ptr->size_approx();\n\t\t}\n\t\treturn size;\n\t}\n\t\n\t\n\t// Returns true if the underlying atomic variables used by\n\t// the queue are lock-free (they should be on most platforms).\n\t// Thread-safe.\n\tstatic constexpr bool is_lock_free()\n\t{\n\t\treturn\n\t\t\tdetails::static_is_lock_free<bool>::value == 2 &&\n\t\t\tdetails::static_is_lock_free<size_t>::value == 2 &&\n\t\t\tdetails::static_is_lock_free<std::uint32_t>::value == 2 &&\n\t\t\tdetails::static_is_lock_free<index_t>::value == 2 &&\n\t\t\tdetails::static_is_lock_free<void*>::value == 2 &&\n\t\t\tdetails::static_is_lock_free<typename details::thread_id_converter<details::thread_id_t>::thread_id_numeric_size_t>::value == 2;\n\t}\n\n\nprivate:\n\tfriend struct ProducerToken;\n\tfriend struct ConsumerToken;\n\tstruct ExplicitProducer;\n\tfriend struct ExplicitProducer;\n\tstruct ImplicitProducer;\n\tfriend struct ImplicitProducer;\n\tfriend class ConcurrentQueueTests;\n\t\t\n\tenum AllocationMode { CanAlloc, CannotAlloc };\n\t\n\t\n\t///////////////////////////////\n\t// Queue methods\n\t///////////////////////////////\n\t\n\ttemplate<AllocationMode canAlloc, typename U>\n\tinline bool inner_enqueue(producer_token_t const& token, U&& element)\n\t{\n\t\treturn static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));\n\t}\n\t\n\ttemplate<AllocationMode canAlloc, typename U>\n\tinline bool inner_enqueue(U&& element)\n\t{\n\t\tauto producer = get_or_add_implicit_producer();\n\t\treturn producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue<canAlloc>(std::forward<U>(element));\n\t}\n\t\n\ttemplate<AllocationMode canAlloc, typename It>\n\tinline bool inner_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)\n\t{\n\t\treturn static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue_bulk<canAlloc>(itemFirst, count);\n\t}\n\t\n\ttemplate<AllocationMode canAlloc, typename It>\n\tinline bool inner_enqueue_bulk(It itemFirst, size_t count)\n\t{\n\t\tauto producer = get_or_add_implicit_producer();\n\t\treturn producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue_bulk<canAlloc>(itemFirst, count);\n\t}\n\t\n\tinline bool update_current_producer_after_rotation(consumer_token_t& token)\n\t{\n\t\t// Ah, there's been a rotation, figure out where we should be!\n\t\tauto tail = producerListTail.load(std::memory_order_acquire);\n\t\tif (token.desiredProducer == nullptr && tail == nullptr) {\n\t\t\treturn false;\n\t\t}\n\t\tauto prodCount = producerCount.load(std::memory_order_relaxed);\n\t\tauto globalOffset = globalExplicitConsumerOffset.load(std::memory_order_relaxed);\n\t\tif ((details::unlikely)(token.desiredProducer == nullptr)) {\n\t\t\t// Aha, first time we're dequeueing anything.\n\t\t\t// Figure out our local position\n\t\t\t// Note: offset is from start, not end, but we're traversing from end -- subtract from count first\n\t\t\tstd::uint32_t offset = prodCount - 1 - (token.initialOffset % prodCount);\n\t\t\ttoken.desiredProducer = tail;\n\t\t\tfor (std::uint32_t i = 0; i != offset; ++i) {\n\t\t\t\ttoken.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();\n\t\t\t\tif (token.desiredProducer == nullptr) {\n\t\t\t\t\ttoken.desiredProducer = tail;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tstd::uint32_t delta = globalOffset - token.lastKnownGlobalOffset;\n\t\tif (delta >= prodCount) {\n\t\t\tdelta = delta % prodCount;\n\t\t}\n\t\tfor (std::uint32_t i = 0; i != delta; ++i) {\n\t\t\ttoken.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();\n\t\t\tif (token.desiredProducer == nullptr) {\n\t\t\t\ttoken.desiredProducer = tail;\n\t\t\t}\n\t\t}\n\t\t\n\t\ttoken.lastKnownGlobalOffset = globalOffset;\n\t\ttoken.currentProducer = token.desiredProducer;\n\t\ttoken.itemsConsumedFromCurrent = 0;\n\t\treturn true;\n\t}\n\t\n\t\n\t///////////////////////////\n\t// Free list\n\t///////////////////////////\n\t\n\ttemplate <typename N>\n\tstruct FreeListNode\n\t{\n\t\tFreeListNode() : freeListRefs(0), freeListNext(nullptr) { }\n\t\t\n\t\tstd::atomic<std::uint32_t> freeListRefs;\n\t\tstd::atomic<N*> freeListNext;\n\t};\n\t\n\t// A simple CAS-based lock-free free list. Not the fastest thing in the world under heavy contention, but\n\t// simple and correct (assuming nodes are never freed until after the free list is destroyed), and fairly\n\t// speedy under low contention.\n\ttemplate<typename N>\t\t// N must inherit FreeListNode or have the same fields (and initialization of them)\n\tstruct FreeList\n\t{\n\t\tFreeList() : freeListHead(nullptr) { }\n\t\tFreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); }\n\t\tvoid swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); }\n\t\t\n\t\tFreeList(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\tFreeList& operator=(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;\n\t\t\n\t\tinline void add(N* node)\n\t\t{\n#ifdef MCDBGQ_NOLOCKFREE_FREELIST\n\t\t\tdebug::DebugLock lock(mutex);\n#endif\t\t\n\t\t\t// We know that the should-be-on-freelist bit is 0 at this point, so it's safe to\n\t\t\t// set it using a fetch_add\n\t\t\tif (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST, std::memory_order_acq_rel) == 0) {\n\t\t\t\t// Oh look! We were the last ones referencing this node, and we know\n\t\t\t\t// we want to add it to the free list, so let's do it!\n\t\t \t\tadd_knowing_refcount_is_zero(node);\n\t\t\t}\n\t\t}\n\t\t\n\t\tinline N* try_get()\n\t\t{\n#ifdef MCDBGQ_NOLOCKFREE_FREELIST\n\t\t\tdebug::DebugLock lock(mutex);\n#endif\t\t\n\t\t\tauto head = freeListHead.load(std::memory_order_acquire);\n\t\t\twhile (head != nullptr) {\n\t\t\t\tauto prevHead = head;\n\t\t\t\tauto refs = head->freeListRefs.load(std::memory_order_relaxed);\n\t\t\t\tif ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong(refs, refs + 1, std::memory_order_acquire, std::memory_order_relaxed)) {\n\t\t\t\t\thead = freeListHead.load(std::memory_order_acquire);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Good, reference count has been incremented (it wasn't at zero), which means we can read the\n\t\t\t\t// next and not worry about it changing between now and the time we do the CAS\n\t\t\t\tauto next = head->freeListNext.load(std::memory_order_relaxed);\n\t\t\t\tif (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) {\n\t\t\t\t\t// Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no\n\t\t\t\t\t// matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on).\n\t\t\t\t\tassert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0);\n\t\t\t\t\t\n\t\t\t\t\t// Decrease refcount twice, once for our ref, and once for the list's ref\n\t\t\t\t\thead->freeListRefs.fetch_sub(2, std::memory_order_release);\n\t\t\t\t\treturn head;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// OK, the head must have changed on us, but we still need to decrease the refcount we increased.\n\t\t\t\t// Note that we don't need to release any memory effects, but we do need to ensure that the reference\n\t\t\t\t// count decrement happens-after the CAS on the head.\n\t\t\t\trefs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel);\n\t\t\t\tif (refs == SHOULD_BE_ON_FREELIST + 1) {\n\t\t\t\t\tadd_knowing_refcount_is_zero(prevHead);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn nullptr;\n\t\t}\n\t\t\n\t\t// Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes)\n\t\tN* head_unsafe() const { return freeListHead.load(std::memory_order_relaxed); }\n\t\t\n\tprivate:\n\t\tinline void add_knowing_refcount_is_zero(N* node)\n\t\t{\n\t\t\t// Since the refcount is zero, and nobody can increase it once it's zero (except us, and we run\n\t\t\t// only one copy of this method per node at a time, i.e. the single thread case), then we know\n\t\t\t// we can safely change the next pointer of the node; however, once the refcount is back above\n\t\t\t// zero, then other threads could increase it (happens under heavy contention, when the refcount\n\t\t\t// goes to zero in between a load and a refcount increment of a node in try_get, then back up to\n\t\t\t// something non-zero, then the refcount increment is done by the other thread) -- so, if the CAS\n\t\t\t// to add the node to the actual list fails, decrease the refcount and leave the add operation to\n\t\t\t// the next thread who puts the refcount back at zero (which could be us, hence the loop).\n\t\t\tauto head = freeListHead.load(std::memory_order_relaxed);\n\t\t\twhile (true) {\n\t\t\t\tnode->freeListNext.store(head, std::memory_order_relaxed);\n\t\t\t\tnode->freeListRefs.store(1, std::memory_order_release);\n\t\t\t\tif (!freeListHead.compare_exchange_strong(head, node, std::memory_order_release, std::memory_order_relaxed)) {\n\t\t\t\t\t// Hmm, the add failed, but we can only try again when the refcount goes back to zero\n\t\t\t\t\tif (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST - 1, std::memory_order_release) == 1) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\tprivate:\n\t\t// Implemented like a stack, but where node order doesn't matter (nodes are inserted out of order under contention)\n\t\tstd::atomic<N*> freeListHead;\n\t\n\tstatic const std::uint32_t REFS_MASK = 0x7FFFFFFF;\n\tstatic const std::uint32_t SHOULD_BE_ON_FREELIST = 0x80000000;\n\t\t\n#ifdef MCDBGQ_NOLOCKFREE_FREELIST\n\t\tdebug::DebugMutex mutex;\n#endif\n\t};\n\t\n\t\n\t///////////////////////////\n\t// Block\n\t///////////////////////////\n\t\n\tenum InnerQueueContext { implicit_context = 0, explicit_context = 1 };\n\t\n\tstruct Block\n\t{\n\t\tBlock()\n\t\t\t: next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), dynamicallyAllocated(true)\n\t\t{\n#ifdef MCDBGQ_TRACKMEM\n\t\t\towner = nullptr;\n#endif\n\t\t}\n\t\t\n\t\ttemplate<InnerQueueContext context>\n\t\tinline bool is_empty() const\n\t\t{\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n\t\t\t\t// Check flags\n\t\t\t\tfor (size_t i = 0; i < BLOCK_SIZE; ++i) {\n\t\t\t\t\tif (!emptyFlags[i].load(std::memory_order_relaxed)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Aha, empty; make sure we have all other memory effects that happened before the empty flags were set\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Check counter\n\t\t\t\tif (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) {\n\t\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tassert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Returns true if the block is now empty (does not apply in explicit context)\n\t\ttemplate<InnerQueueContext context>\n\t\tinline bool set_empty(MOODYCAMEL_MAYBE_UNUSED index_t i)\n\t\t{\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n\t\t\t\t// Set flag\n\t\t\t\tassert(!emptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].load(std::memory_order_relaxed));\n\t\t\t\temptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].store(true, std::memory_order_release);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Increment counter\n\t\t\t\tauto prevVal = elementsCompletelyDequeued.fetch_add(1, std::memory_order_release);\n\t\t\t\tassert(prevVal < BLOCK_SIZE);\n\t\t\t\treturn prevVal == BLOCK_SIZE - 1;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0).\n\t\t// Returns true if the block is now empty (does not apply in explicit context).\n\t\ttemplate<InnerQueueContext context>\n\t\tinline bool set_many_empty(MOODYCAMEL_MAYBE_UNUSED index_t i, size_t count)\n\t\t{\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n\t\t\t\t// Set flags\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_release);\n\t\t\t\ti = BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1)) - count + 1;\n\t\t\t\tfor (size_t j = 0; j != count; ++j) {\n\t\t\t\t\tassert(!emptyFlags[i + j].load(std::memory_order_relaxed));\n\t\t\t\t\temptyFlags[i + j].store(true, std::memory_order_relaxed);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Increment counter\n\t\t\t\tauto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release);\n\t\t\t\tassert(prevVal + count <= BLOCK_SIZE);\n\t\t\t\treturn prevVal + count == BLOCK_SIZE;\n\t\t\t}\n\t\t}\n\t\t\n\t\ttemplate<InnerQueueContext context>\n\t\tinline void set_all_empty()\n\t\t{\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n\t\t\t\t// Set all flags\n\t\t\t\tfor (size_t i = 0; i != BLOCK_SIZE; ++i) {\n\t\t\t\t\temptyFlags[i].store(true, std::memory_order_relaxed);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Reset counter\n\t\t\t\telementsCompletelyDequeued.store(BLOCK_SIZE, std::memory_order_relaxed);\n\t\t\t}\n\t\t}\n\t\t\n\t\ttemplate<InnerQueueContext context>\n\t\tinline void reset_empty()\n\t\t{\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {\n\t\t\t\t// Reset flags\n\t\t\t\tfor (size_t i = 0; i != BLOCK_SIZE; ++i) {\n\t\t\t\t\temptyFlags[i].store(false, std::memory_order_relaxed);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Reset counter\n\t\t\t\telementsCompletelyDequeued.store(0, std::memory_order_relaxed);\n\t\t\t}\n\t\t}\n\t\t\n\t\tinline T* operator[](index_t idx) MOODYCAMEL_NOEXCEPT { return static_cast<T*>(static_cast<void*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }\n\t\tinline T const* operator[](index_t idx) const MOODYCAMEL_NOEXCEPT { return static_cast<T const*>(static_cast<void const*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }\n\t\t\n\tprivate:\n\t\tstatic_assert(std::alignment_of<T>::value <= sizeof(T), \"The queue does not support types with an alignment greater than their size at this time\");\n\t\tMOODYCAMEL_ALIGNED_TYPE_LIKE(char[sizeof(T) * BLOCK_SIZE], T) elements;\n\tpublic:\n\t\tBlock* next;\n\t\tstd::atomic<size_t> elementsCompletelyDequeued;\n\t\tstd::atomic<bool> emptyFlags[BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD ? BLOCK_SIZE : 1];\n\tpublic:\n\t\tstd::atomic<std::uint32_t> freeListRefs;\n\t\tstd::atomic<Block*> freeListNext;\n\t\tbool dynamicallyAllocated;\t\t// Perhaps a better name for this would be 'isNotPartOfInitialBlockPool'\n\t\t\n#ifdef MCDBGQ_TRACKMEM\n\t\tvoid* owner;\n#endif\n\t};\n\tstatic_assert(std::alignment_of<Block>::value >= std::alignment_of<T>::value, \"Internal error: Blocks must be at least as aligned as the type they are wrapping\");\n\n\n#ifdef MCDBGQ_TRACKMEM\npublic:\n\tstruct MemStats;\nprivate:\n#endif\n\t\n\t///////////////////////////\n\t// Producer base\n\t///////////////////////////\n\t\n\tstruct ProducerBase : public details::ConcurrentQueueProducerTypelessBase\n\t{\n\t\tProducerBase(ConcurrentQueue* parent_, bool isExplicit_) :\n\t\t\ttailIndex(0),\n\t\t\theadIndex(0),\n\t\t\tdequeueOptimisticCount(0),\n\t\t\tdequeueOvercommit(0),\n\t\t\ttailBlock(nullptr),\n\t\t\tisExplicit(isExplicit_),\n\t\t\tparent(parent_)\n\t\t{\n\t\t}\n\t\t\n\t\tvirtual ~ProducerBase() { }\n\t\t\n\t\ttemplate<typename U>\n\t\tinline bool dequeue(U& element)\n\t\t{\n\t\t\tif (isExplicit) {\n\t\t\t\treturn static_cast<ExplicitProducer*>(this)->dequeue(element);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn static_cast<ImplicitProducer*>(this)->dequeue(element);\n\t\t\t}\n\t\t}\n\t\t\n\t\ttemplate<typename It>\n\t\tinline size_t dequeue_bulk(It& itemFirst, size_t max)\n\t\t{\n\t\t\tif (isExplicit) {\n\t\t\t\treturn static_cast<ExplicitProducer*>(this)->dequeue_bulk(itemFirst, max);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn static_cast<ImplicitProducer*>(this)->dequeue_bulk(itemFirst, max);\n\t\t\t}\n\t\t}\n\t\t\n\t\tinline ProducerBase* next_prod() const { return static_cast<ProducerBase*>(next); }\n\t\t\n\t\tinline size_t size_approx() const\n\t\t{\n\t\t\tauto tail = tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto head = headIndex.load(std::memory_order_relaxed);\n\t\t\treturn details::circular_less_than(head, tail) ? static_cast<size_t>(tail - head) : 0;\n\t\t}\n\t\t\n\t\tinline index_t getTail() const { return tailIndex.load(std::memory_order_relaxed); }\n\tprotected:\n\t\tstd::atomic<index_t> tailIndex;\t\t// Where to enqueue to next\n\t\tstd::atomic<index_t> headIndex;\t\t// Where to dequeue from next\n\t\t\n\t\tstd::atomic<index_t> dequeueOptimisticCount;\n\t\tstd::atomic<index_t> dequeueOvercommit;\n\t\t\n\t\tBlock* tailBlock;\n\t\t\n\tpublic:\n\t\tbool isExplicit;\n\t\tConcurrentQueue* parent;\n\t\t\n\tprotected:\n#ifdef MCDBGQ_TRACKMEM\n\t\tfriend struct MemStats;\n#endif\n\t};\n\t\n\t\n\t///////////////////////////\n\t// Explicit queue\n\t///////////////////////////\n\t\t\n\tstruct ExplicitProducer : public ProducerBase\n\t{\n\t\texplicit ExplicitProducer(ConcurrentQueue* parent_) :\n\t\t\tProducerBase(parent_, true),\n\t\t\tblockIndex(nullptr),\n\t\t\tpr_blockIndexSlotsUsed(0),\n\t\t\tpr_blockIndexSize(EXPLICIT_INITIAL_INDEX_SIZE >> 1),\n\t\t\tpr_blockIndexFront(0),\n\t\t\tpr_blockIndexEntries(nullptr),\n\t\t\tpr_blockIndexRaw(nullptr)\n\t\t{\n\t\t\tsize_t poolBasedIndexSize = details::ceil_to_pow_2(parent_->initialBlockPoolSize) >> 1;\n\t\t\tif (poolBasedIndexSize > pr_blockIndexSize) {\n\t\t\t\tpr_blockIndexSize = poolBasedIndexSize;\n\t\t\t}\n\t\t\t\n\t\t\tnew_block_index(0);\t\t// This creates an index with double the number of current entries, i.e. EXPLICIT_INITIAL_INDEX_SIZE\n\t\t}\n\t\t\n\t\t~ExplicitProducer() override\n\t\t{\n\t\t\t// Destruct any elements not yet dequeued.\n\t\t\t// Since we're in the destructor, we can assume all elements\n\t\t\t// are either completely dequeued or completely not (no halfways).\n\t\t\tif (this->tailBlock != nullptr) {\t\t// Note this means there must be a block index too\n\t\t\t\t// First find the block that's partially dequeued, if any\n\t\t\t\tBlock* halfDequeuedBlock = nullptr;\n\t\t\t\tif ((this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) != 0) {\n\t\t\t\t\t// The head's not on a block boundary, meaning a block somewhere is partially dequeued\n\t\t\t\t\t// (or the head block is the tail block and was fully dequeued, but the head/tail are still not on a boundary)\n\t\t\t\t\tsize_t i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & (pr_blockIndexSize - 1);\n\t\t\t\t\twhile (details::circular_less_than<index_t>(pr_blockIndexEntries[i].base + BLOCK_SIZE, this->headIndex.load(std::memory_order_relaxed))) {\n\t\t\t\t\t\ti = (i + 1) & (pr_blockIndexSize - 1);\n\t\t\t\t\t}\n\t\t\t\t\tassert(details::circular_less_than<index_t>(pr_blockIndexEntries[i].base, this->headIndex.load(std::memory_order_relaxed)));\n\t\t\t\t\thalfDequeuedBlock = pr_blockIndexEntries[i].block;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Start at the head block (note the first line in the loop gives us the head from the tail on the first iteration)\n\t\t\t\tauto block = this->tailBlock;\n\t\t\t\tdo {\n\t\t\t\t\tblock = block->next;\n\t\t\t\t\tif (block->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tsize_t i = 0;\t// Offset into block\n\t\t\t\t\tif (block == halfDequeuedBlock) {\n\t\t\t\t\t\ti = static_cast<size_t>(this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Walk through all the items in the block; if this is the tail block, we need to stop when we reach the tail index\n\t\t\t\t\tauto lastValidIndex = (this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 ? BLOCK_SIZE : static_cast<size_t>(this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));\n\t\t\t\t\twhile (i != BLOCK_SIZE && (block != this->tailBlock || i != lastValidIndex)) {\n\t\t\t\t\t\t(*block)[i++]->~T();\n\t\t\t\t\t}\n\t\t\t\t} while (block != this->tailBlock);\n\t\t\t}\n\t\t\t\n\t\t\t// Destroy all blocks that we own\n\t\t\tif (this->tailBlock != nullptr) {\n\t\t\t\tauto block = this->tailBlock;\n\t\t\t\tdo {\n\t\t\t\t\tauto nextBlock = block->next;\n\t\t\t\t\tthis->parent->add_block_to_free_list(block);\n\t\t\t\t\tblock = nextBlock;\n\t\t\t\t} while (block != this->tailBlock);\n\t\t\t}\n\t\t\t\n\t\t\t// Destroy the block indices\n\t\t\tauto header = static_cast<BlockIndexHeader*>(pr_blockIndexRaw);\n\t\t\twhile (header != nullptr) {\n\t\t\t\tauto prev = static_cast<BlockIndexHeader*>(header->prev);\n\t\t\t\theader->~BlockIndexHeader();\n\t\t\t\t(Traits::free)(header);\n\t\t\t\theader = prev;\n\t\t\t}\n\t\t}\n\t\t\n\t\ttemplate<AllocationMode allocMode, typename U>\n\t\tinline bool enqueue(U&& element)\n\t\t{\n\t\t\tindex_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tindex_t newTailIndex = 1 + currentTailIndex;\n\t\t\tif ((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n\t\t\t\t// We reached the end of a block, start a new one\n\t\t\t\tauto startBlock = this->tailBlock;\n\t\t\t\tauto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;\n\t\t\t\tif (this->tailBlock != nullptr && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n\t\t\t\t\t// We can re-use the block ahead of us, it's empty!\t\t\t\t\t\n\t\t\t\t\tthis->tailBlock = this->tailBlock->next;\n\t\t\t\t\tthis->tailBlock->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n\t\t\t\t\t\n\t\t\t\t\t// We'll put the block on the block index (guaranteed to be room since we're conceptually removing the\n\t\t\t\t\t// last block from it first -- except instead of removing then adding, we can just overwrite).\n\t\t\t\t\t// Note that there must be a valid block index here, since even if allocation failed in the ctor,\n\t\t\t\t\t// it would have been re-attempted when adding the first block to the queue; since there is such\n\t\t\t\t\t// a block, a block index must have been successfully allocated.\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Whatever head value we see here is >= the last value we saw here (relatively),\n\t\t\t\t\t// and <= its current value. Since we have the most recent tail, the head must be\n\t\t\t\t\t// <= to it.\n\t\t\t\t\tauto head = this->headIndex.load(std::memory_order_relaxed);\n\t\t\t\t\tassert(!details::circular_less_than<index_t>(currentTailIndex, head));\n\t\t\t\t\tif (!details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE)\n\t\t\t\t\t\t|| (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) {\n\t\t\t\t\t\t// We can't enqueue in another block because there's not enough leeway -- the\n\t\t\t\t\t\t// tail could surpass the head by the time the block fills up! (Or we'll exceed\n\t\t\t\t\t\t// the size limit, if the second part of the condition was true.)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t// We're going to need a new block; check that the block index has room\n\t\t\t\t\tif (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize) {\n\t\t\t\t\t\t// Hmm, the circular block index is already full -- we'll need\n\t\t\t\t\t\t// to allocate a new index. Note pr_blockIndexRaw can only be nullptr if\n\t\t\t\t\t\t// the initial allocation failed in the constructor.\n\t\t\t\t\t\t\n\t\t\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (allocMode == CannotAlloc) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (!new_block_index(pr_blockIndexSlotsUsed)) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Insert a new block in the circular linked list\n\t\t\t\t\tauto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n\t\t\t\t\tif (newBlock == nullptr) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n#ifdef MCDBGQ_TRACKMEM\n\t\t\t\t\tnewBlock->owner = this;\n#endif\n\t\t\t\t\tnewBlock->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n\t\t\t\t\tif (this->tailBlock == nullptr) {\n\t\t\t\t\t\tnewBlock->next = newBlock;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnewBlock->next = this->tailBlock->next;\n\t\t\t\t\t\tthis->tailBlock->next = newBlock;\n\t\t\t\t\t}\n\t\t\t\t\tthis->tailBlock = newBlock;\n\t\t\t\t\t++pr_blockIndexSlotsUsed;\n\t\t\t\t}\n\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {\n\t\t\t\t\t// The constructor may throw. We want the element not to appear in the queue in\n\t\t\t\t\t// that case (without corrupting the queue):\n\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\tnew ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n\t\t\t\t\t}\n\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\t// Revert change to the current block, but leave the new block available\n\t\t\t\t\t\t// for next time\n\t\t\t\t\t\tpr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n\t\t\t\t\t\tthis->tailBlock = startBlock == nullptr ? this->tailBlock : startBlock;\n\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t(void)startBlock;\n\t\t\t\t\t(void)originalBlockIndexSlotsUsed;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Add block to block index\n\t\t\t\tauto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n\t\t\t\tentry.base = currentTailIndex;\n\t\t\t\tentry.block = this->tailBlock;\n\t\t\t\tblockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release);\n\t\t\t\tpr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n\t\t\t\t\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {\n\t\t\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Enqueue\n\t\t\tnew ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n\t\t\t\n\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\ttemplate<typename U>\n\t\tbool dequeue(U& element)\n\t\t{\n\t\t\tauto tail = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n\t\t\tif (details::circular_less_than<index_t>(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) {\n\t\t\t\t// Might be something to dequeue, let's give it a try\n\t\t\t\t\n\t\t\t\t// Note that this if is purely for performance purposes in the common case when the queue is\n\t\t\t\t// empty and the values are eventually consistent -- we may enter here spuriously.\n\t\t\t\t\n\t\t\t\t// Note that whatever the values of overcommit and tail are, they are not going to change (unless we\n\t\t\t\t// change them) and must be the same value at this point (inside the if) as when the if condition was\n\t\t\t\t// evaluated.\n\n\t\t\t\t// We insert an acquire fence here to synchronize-with the release upon incrementing dequeueOvercommit below.\n\t\t\t\t// This ensures that whatever the value we got loaded into overcommit, the load of dequeueOptisticCount in\n\t\t\t\t// the fetch_add below will result in a value at least as recent as that (and therefore at least as large).\n\t\t\t\t// Note that I believe a compiler (signal) fence here would be sufficient due to the nature of fetch_add (all\n\t\t\t\t// read-modify-write operations are guaranteed to work on the latest value in the modification order), but\n\t\t\t\t// unfortunately that can't be shown to be correct using only the C++11 standard.\n\t\t\t\t// See http://stackoverflow.com/questions/18223161/what-are-the-c11-memory-ordering-guarantees-in-this-corner-case\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\t\n\t\t\t\t// Increment optimistic counter, then check if it went over the boundary\n\t\t\t\tauto myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed);\n\t\t\t\t\n\t\t\t\t// Note that since dequeueOvercommit must be <= dequeueOptimisticCount (because dequeueOvercommit is only ever\n\t\t\t\t// incremented after dequeueOptimisticCount -- this is enforced in the `else` block below), and since we now\n\t\t\t\t// have a version of dequeueOptimisticCount that is at least as recent as overcommit (due to the release upon\n\t\t\t\t// incrementing dequeueOvercommit and the acquire above that synchronizes with it), overcommit <= myDequeueCount.\n\t\t\t\t// However, we can't assert this since both dequeueOptimisticCount and dequeueOvercommit may (independently)\n\t\t\t\t// overflow; in such a case, though, the logic still holds since the difference between the two is maintained.\n\t\t\t\t\n\t\t\t\t// Note that we reload tail here in case it changed; it will be the same value as before or greater, since\n\t\t\t\t// this load is sequenced after (happens after) the earlier load above. This is supported by read-read\n\t\t\t\t// coherency (as defined in the standard), explained here: http://en.cppreference.com/w/cpp/atomic/memory_order\n\t\t\t\ttail = this->tailIndex.load(std::memory_order_acquire);\n\t\t\t\tif ((details::likely)(details::circular_less_than<index_t>(myDequeueCount - overcommit, tail))) {\n\t\t\t\t\t// Guaranteed to be at least one element to dequeue!\n\t\t\t\t\t\n\t\t\t\t\t// Get the index. Note that since there's guaranteed to be at least one element, this\n\t\t\t\t\t// will never exceed tail. We need to do an acquire-release fence here since it's possible\n\t\t\t\t\t// that whatever condition got us to this point was for an earlier enqueued element (that\n\t\t\t\t\t// we already see the memory effects for), but that by the time we increment somebody else\n\t\t\t\t\t// has incremented it, and we need to see the memory effects for *that* element, which is\n\t\t\t\t\t// in such a case is necessarily visible on the thread that incremented it in the first\n\t\t\t\t\t// place with the more current condition (they must have acquired a tail that is at least\n\t\t\t\t\t// as recent).\n\t\t\t\t\tauto index = this->headIndex.fetch_add(1, std::memory_order_acq_rel);\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t// Determine which block the element is in\n\t\t\t\t\t\n\t\t\t\t\tauto localBlockIndex = blockIndex.load(std::memory_order_acquire);\n\t\t\t\t\tauto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);\n\t\t\t\t\t\n\t\t\t\t\t// We need to be careful here about subtracting and dividing because of index wrap-around.\n\t\t\t\t\t// When an index wraps, we need to preserve the sign of the offset when dividing it by the\n\t\t\t\t\t// block size (in order to get a correct signed block count offset in all cases):\n\t\t\t\t\tauto headBase = localBlockIndex->entries[localBlockIndexHead].base;\n\t\t\t\t\tauto blockBaseIndex = index & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\t\t\tauto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(blockBaseIndex - headBase) / static_cast<typename std::make_signed<index_t>::type>(BLOCK_SIZE));\n\t\t\t\t\tauto block = localBlockIndex->entries[(localBlockIndexHead + offset) & (localBlockIndex->size - 1)].block;\n\t\t\t\t\t\n\t\t\t\t\t// Dequeue\n\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\tif (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) {\n\t\t\t\t\t\t// Make sure the element is still fully dequeued and destroyed even if the assignment\n\t\t\t\t\t\t// throws\n\t\t\t\t\t\tstruct Guard {\n\t\t\t\t\t\t\tBlock* block;\n\t\t\t\t\t\t\tindex_t index;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t~Guard()\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t(*block)[index]->~T();\n\t\t\t\t\t\t\t\tblock->ConcurrentQueue::Block::template set_empty<explicit_context>(index);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} guard = { block, index };\n\n\t\t\t\t\t\telement = std::move(el); // NOLINT\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\telement = std::move(el); // NOLINT\n\t\t\t\t\t\tel.~T(); // NOLINT\n\t\t\t\t\t\tblock->ConcurrentQueue::Block::template set_empty<explicit_context>(index);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent\n\t\t\t\t\tthis->dequeueOvercommit.fetch_add(1, std::memory_order_release);\t\t// Release so that the fetch_add on dequeueOptimisticCount is guaranteed to happen before this write\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\ttemplate<AllocationMode allocMode, typename It>\n\t\tbool MOODYCAMEL_NO_TSAN enqueue_bulk(It itemFirst, size_t count)\n\t\t{\n\t\t\t// First, we need to make sure we have enough room to enqueue all of the elements;\n\t\t\t// this means pre-allocating blocks and putting them in the block index (but only if\n\t\t\t// all the allocations succeeded).\n\t\t\tindex_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto startBlock = this->tailBlock;\n\t\t\tauto originalBlockIndexFront = pr_blockIndexFront;\n\t\t\tauto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;\n\t\t\t\n\t\t\tBlock* firstAllocatedBlock = nullptr;\n\t\t\t\n\t\t\t// Figure out how many blocks we'll need to allocate, and do so\n\t\t\tsize_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));\n\t\t\tindex_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\tif (blockBaseDiff > 0) {\n\t\t\t\t// Allocate as many blocks as possible from ahead\n\t\t\t\twhile (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {\n\t\t\t\t\tblockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\tcurrentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\n\t\t\t\t\tthis->tailBlock = this->tailBlock->next;\n\t\t\t\t\tfirstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;\n\t\t\t\t\t\n\t\t\t\t\tauto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n\t\t\t\t\tentry.base = currentTailIndex;\n\t\t\t\t\tentry.block = this->tailBlock;\n\t\t\t\t\tpr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Now allocate as many blocks as necessary from the block pool\n\t\t\t\twhile (blockBaseDiff > 0) {\n\t\t\t\t\tblockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\tcurrentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\n\t\t\t\t\tauto head = this->headIndex.load(std::memory_order_relaxed);\n\t\t\t\t\tassert(!details::circular_less_than<index_t>(currentTailIndex, head));\n\t\t\t\t\tbool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));\n\t\t\t\t\tif (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) {\n\t\t\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (allocMode == CannotAlloc) {\n\t\t\t\t\t\t\t// Failed to allocate, undo changes (but keep injected blocks)\n\t\t\t\t\t\t\tpr_blockIndexFront = originalBlockIndexFront;\n\t\t\t\t\t\t\tpr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n\t\t\t\t\t\t\tthis->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (full || !new_block_index(originalBlockIndexSlotsUsed)) {\n\t\t\t\t\t\t\t// Failed to allocate, undo changes (but keep injected blocks)\n\t\t\t\t\t\t\tpr_blockIndexFront = originalBlockIndexFront;\n\t\t\t\t\t\t\tpr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n\t\t\t\t\t\t\tthis->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// pr_blockIndexFront is updated inside new_block_index, so we need to\n\t\t\t\t\t\t// update our fallback value too (since we keep the new index even if we\n\t\t\t\t\t\t// later fail)\n\t\t\t\t\t\toriginalBlockIndexFront = originalBlockIndexSlotsUsed;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Insert a new block in the circular linked list\n\t\t\t\t\tauto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n\t\t\t\t\tif (newBlock == nullptr) {\n\t\t\t\t\t\tpr_blockIndexFront = originalBlockIndexFront;\n\t\t\t\t\t\tpr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n\t\t\t\t\t\tthis->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t\n#ifdef MCDBGQ_TRACKMEM\n\t\t\t\t\tnewBlock->owner = this;\n#endif\n\t\t\t\t\tnewBlock->ConcurrentQueue::Block::template set_all_empty<explicit_context>();\n\t\t\t\t\tif (this->tailBlock == nullptr) {\n\t\t\t\t\t\tnewBlock->next = newBlock;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnewBlock->next = this->tailBlock->next;\n\t\t\t\t\t\tthis->tailBlock->next = newBlock;\n\t\t\t\t\t}\n\t\t\t\t\tthis->tailBlock = newBlock;\n\t\t\t\t\tfirstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;\n\t\t\t\t\t\n\t\t\t\t\t++pr_blockIndexSlotsUsed;\n\t\t\t\t\t\n\t\t\t\t\tauto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];\n\t\t\t\t\tentry.base = currentTailIndex;\n\t\t\t\t\tentry.block = this->tailBlock;\n\t\t\t\t\tpr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Excellent, all allocations succeeded. Reset each block's emptiness before we fill them up, and\n\t\t\t\t// publish the new block index front\n\t\t\t\tauto block = firstAllocatedBlock;\n\t\t\t\twhile (true) {\n\t\t\t\t\tblock->ConcurrentQueue::Block::template reset_empty<explicit_context>();\n\t\t\t\t\tif (block == this->tailBlock) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tblock = block->next;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {\n\t\t\t\t\tblockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Enqueue, one block at a time\n\t\t\tindex_t newTailIndex = startTailIndex + static_cast<index_t>(count);\n\t\t\tcurrentTailIndex = startTailIndex;\n\t\t\tauto endBlock = this->tailBlock;\n\t\t\tthis->tailBlock = startBlock;\n\t\t\tassert((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0);\n\t\t\tif ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) {\n\t\t\t\tthis->tailBlock = firstAllocatedBlock;\n\t\t\t}\n\t\t\twhile (true) {\n\t\t\t\tindex_t stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\tif (details::circular_less_than<index_t>(newTailIndex, stopIndex)) {\n\t\t\t\t\tstopIndex = newTailIndex;\n\t\t\t\t}\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {\n\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\tnew ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\t\t// Must use copy constructor even if move constructor is available\n\t\t\t\t\t\t\t// because we may have to revert if there's an exception.\n\t\t\t\t\t\t\t// Sorry about the horrible templated next line, but it was the only way\n\t\t\t\t\t\t\t// to disable moving *at compile time*, which is important because a type\n\t\t\t\t\t\t\t// may only define a (noexcept) move constructor, and so calls to the\n\t\t\t\t\t\t\t// cctor will not compile, even if they are in an if branch that will never\n\t\t\t\t\t\t\t// be executed\n\t\t\t\t\t\t\tnew ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst));\n\t\t\t\t\t\t\t++currentTailIndex;\n\t\t\t\t\t\t\t++itemFirst;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\t// Oh dear, an exception's been thrown -- destroy the elements that\n\t\t\t\t\t\t// were enqueued so far and revert the entire bulk operation (we'll keep\n\t\t\t\t\t\t// any allocated blocks in our linked list for later, though).\n\t\t\t\t\t\tauto constructedStopIndex = currentTailIndex;\n\t\t\t\t\t\tauto lastBlockEnqueued = this->tailBlock;\n\t\t\t\t\t\t\n\t\t\t\t\t\tpr_blockIndexFront = originalBlockIndexFront;\n\t\t\t\t\t\tpr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;\n\t\t\t\t\t\tthis->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!details::is_trivially_destructible<T>::value) {\n\t\t\t\t\t\t\tauto block = startBlock;\n\t\t\t\t\t\t\tif ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n\t\t\t\t\t\t\t\tblock = firstAllocatedBlock;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcurrentTailIndex = startTailIndex;\n\t\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\t\tstopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\t\tif (details::circular_less_than<index_t>(constructedStopIndex, stopIndex)) {\n\t\t\t\t\t\t\t\t\tstopIndex = constructedStopIndex;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\t\t\t\t(*block)[currentTailIndex++]->~T();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (block == lastBlockEnqueued) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tblock = block->next;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this->tailBlock == endBlock) {\n\t\t\t\t\tassert(currentTailIndex == newTailIndex);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis->tailBlock = this->tailBlock->next;\n\t\t\t}\n\t\t\t\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {\n\t\t\t\tif (firstAllocatedBlock != nullptr)\n\t\t\t\t\tblockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release);\n\t\t\t}\n\t\t\t\n\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\ttemplate<typename It>\n\t\tsize_t dequeue_bulk(It& itemFirst, size_t max)\n\t\t{\n\t\t\tauto tail = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n\t\t\tauto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));\n\t\t\tif (details::circular_less_than<size_t>(0, desiredCount)) {\n\t\t\t\tdesiredCount = desiredCount < max ? desiredCount : max;\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\t\n\t\t\t\tauto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);\n\t\t\t\t\n\t\t\t\ttail = this->tailIndex.load(std::memory_order_acquire);\n\t\t\t\tauto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));\n\t\t\t\tif (details::circular_less_than<size_t>(0, actualCount)) {\n\t\t\t\t\tactualCount = desiredCount < actualCount ? desiredCount : actualCount;\n\t\t\t\t\tif (actualCount < desiredCount) {\n\t\t\t\t\t\tthis->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get the first index. Note that since there's guaranteed to be at least actualCount elements, this\n\t\t\t\t\t// will never exceed tail.\n\t\t\t\t\tauto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);\n\t\t\t\t\t\n\t\t\t\t\t// Determine which block the first element is in\n\t\t\t\t\tauto localBlockIndex = blockIndex.load(std::memory_order_acquire);\n\t\t\t\t\tauto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);\n\t\t\t\t\t\n\t\t\t\t\tauto headBase = localBlockIndex->entries[localBlockIndexHead].base;\n\t\t\t\t\tauto firstBlockBaseIndex = firstIndex & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\t\t\tauto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(firstBlockBaseIndex - headBase) / static_cast<typename std::make_signed<index_t>::type>(BLOCK_SIZE));\n\t\t\t\t\tauto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1);\n\t\t\t\t\t\n\t\t\t\t\t// Iterate the blocks and dequeue\n\t\t\t\t\tauto index = firstIndex;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tauto firstIndexInBlock = index;\n\t\t\t\t\t\tindex_t endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\tendIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n\t\t\t\t\t\tauto block = localBlockIndex->entries[indexIndex].block;\n\t\t\t\t\t\tif (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {\n\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\t\t\t\t*itemFirst++ = std::move(el);\n\t\t\t\t\t\t\t\tel.~T();\n\t\t\t\t\t\t\t\t++index;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\t\t\t\t\t*itemFirst = std::move(el);\n\t\t\t\t\t\t\t\t\t++itemFirst;\n\t\t\t\t\t\t\t\t\tel.~T();\n\t\t\t\t\t\t\t\t\t++index;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\t\t\t// It's too late to revert the dequeue, but we can make sure that all\n\t\t\t\t\t\t\t\t// the dequeued objects are properly destroyed and the block index\n\t\t\t\t\t\t\t\t// (and empty count) are properly updated before we propagate the exception\n\t\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t\tblock = localBlockIndex->entries[indexIndex].block;\n\t\t\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\t\t\t(*block)[index++]->~T();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tblock->ConcurrentQueue::Block::template set_many_empty<explicit_context>(firstIndexInBlock, static_cast<size_t>(endIndex - firstIndexInBlock));\n\t\t\t\t\t\t\t\t\tindexIndex = (indexIndex + 1) & (localBlockIndex->size - 1);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfirstIndexInBlock = index;\n\t\t\t\t\t\t\t\t\tendIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\t\t\tendIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n\t\t\t\t\t\t\t\t} while (index != firstIndex + actualCount);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tblock->ConcurrentQueue::Block::template set_many_empty<explicit_context>(firstIndexInBlock, static_cast<size_t>(endIndex - firstIndexInBlock));\n\t\t\t\t\t\tindexIndex = (indexIndex + 1) & (localBlockIndex->size - 1);\n\t\t\t\t\t} while (index != firstIndex + actualCount);\n\t\t\t\t\t\n\t\t\t\t\treturn actualCount;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent\n\t\t\t\t\tthis->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn 0;\n\t\t}\n\t\t\n\tprivate:\n\t\tstruct BlockIndexEntry\n\t\t{\n\t\t\tindex_t base;\n\t\t\tBlock* block;\n\t\t};\n\t\t\n\t\tstruct BlockIndexHeader\n\t\t{\n\t\t\tsize_t size;\n\t\t\tstd::atomic<size_t> front;\t\t// Current slot (not next, like pr_blockIndexFront)\n\t\t\tBlockIndexEntry* entries;\n\t\t\tvoid* prev;\n\t\t};\n\t\t\n\t\t\n\t\tbool new_block_index(size_t numberOfFilledSlotsToExpose)\n\t\t{\n\t\t\tauto prevBlockSizeMask = pr_blockIndexSize - 1;\n\t\t\t\n\t\t\t// Create the new block\n\t\t\tpr_blockIndexSize <<= 1;\n\t\t\tauto newRawPtr = static_cast<char*>((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * pr_blockIndexSize));\n\t\t\tif (newRawPtr == nullptr) {\n\t\t\t\tpr_blockIndexSize >>= 1;\t\t// Reset to allow graceful retry\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tauto newBlockIndexEntries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(newRawPtr + sizeof(BlockIndexHeader)));\n\t\t\t\n\t\t\t// Copy in all the old indices, if any\n\t\t\tsize_t j = 0;\n\t\t\tif (pr_blockIndexSlotsUsed != 0) {\n\t\t\t\tauto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask;\n\t\t\t\tdo {\n\t\t\t\t\tnewBlockIndexEntries[j++] = pr_blockIndexEntries[i];\n\t\t\t\t\ti = (i + 1) & prevBlockSizeMask;\n\t\t\t\t} while (i != pr_blockIndexFront);\n\t\t\t}\n\t\t\t\n\t\t\t// Update everything\n\t\t\tauto header = new (newRawPtr) BlockIndexHeader;\n\t\t\theader->size = pr_blockIndexSize;\n\t\t\theader->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed);\n\t\t\theader->entries = newBlockIndexEntries;\n\t\t\theader->prev = pr_blockIndexRaw;\t\t// we link the new block to the old one so we can free it later\n\t\t\t\n\t\t\tpr_blockIndexFront = j;\n\t\t\tpr_blockIndexEntries = newBlockIndexEntries;\n\t\t\tpr_blockIndexRaw = newRawPtr;\n\t\t\tblockIndex.store(header, std::memory_order_release);\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\tprivate:\n\t\tstd::atomic<BlockIndexHeader*> blockIndex;\n\t\t\n\t\t// To be used by producer only -- consumer must use the ones in referenced by blockIndex\n\t\tsize_t pr_blockIndexSlotsUsed;\n\t\tsize_t pr_blockIndexSize;\n\t\tsize_t pr_blockIndexFront;\t\t// Next slot (not current)\n\t\tBlockIndexEntry* pr_blockIndexEntries;\n\t\tvoid* pr_blockIndexRaw;\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\tpublic:\n\t\tExplicitProducer* nextExplicitProducer;\n\tprivate:\n#endif\n\t\t\n#ifdef MCDBGQ_TRACKMEM\n\t\tfriend struct MemStats;\n#endif\n\t};\n\t\n\t\n\t//////////////////////////////////\n\t// Implicit queue\n\t//////////////////////////////////\n\t\n\tstruct ImplicitProducer : public ProducerBase\n\t{\t\t\t\n\t\tImplicitProducer(ConcurrentQueue* parent_) :\n\t\t\tProducerBase(parent_, false),\n\t\t\tnextBlockIndexCapacity(IMPLICIT_INITIAL_INDEX_SIZE),\n\t\t\tblockIndex(nullptr)\n\t\t{\n\t\t\tnew_block_index();\n\t\t}\n\t\t\n\t\t~ImplicitProducer() override\n\t\t{\n\t\t\t// Note that since we're in the destructor we can assume that all enqueue/dequeue operations\n\t\t\t// completed already; this means that all undequeued elements are placed contiguously across\n\t\t\t// contiguous blocks, and that only the first and last remaining blocks can be only partially\n\t\t\t// empty (all other remaining blocks must be completely full).\n\t\t\t\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\t\t\t// Unregister ourselves for thread termination notification\n\t\t\tif (!this->inactive.load(std::memory_order_relaxed)) {\n\t\t\t\tdetails::ThreadExitNotifier::unsubscribe(&threadExitListener);\n\t\t\t}\n#endif\n\t\t\t\n\t\t\t// Destroy all remaining elements!\n\t\t\tauto tail = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto index = this->headIndex.load(std::memory_order_relaxed);\n\t\t\tBlock* block = nullptr;\n\t\t\tassert(index == tail || details::circular_less_than(index, tail));\n\t\t\tbool forceFreeLastBlock = index != tail;\t\t// If we enter the loop, then the last (tail) block will not be freed\n\t\t\twhile (index != tail) {\n\t\t\t\tif ((index & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 || block == nullptr) {\n\t\t\t\t\tif (block != nullptr) {\n\t\t\t\t\t\t// Free the old block\n\t\t\t\t\t\tthis->parent->add_block_to_free_list(block);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tblock = get_block_index_entry_for_index(index)->value.load(std::memory_order_relaxed);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t((*block)[index])->~T();\n\t\t\t\t++index;\n\t\t\t}\n\t\t\t// Even if the queue is empty, there's still one block that's not on the free list\n\t\t\t// (unless the head index reached the end of it, in which case the tail will be poised\n\t\t\t// to create a new block).\n\t\t\tif (this->tailBlock != nullptr && (forceFreeLastBlock || (tail & static_cast<index_t>(BLOCK_SIZE - 1)) != 0)) {\n\t\t\t\tthis->parent->add_block_to_free_list(this->tailBlock);\n\t\t\t}\n\t\t\t\n\t\t\t// Destroy block index\n\t\t\tauto localBlockIndex = blockIndex.load(std::memory_order_relaxed);\n\t\t\tif (localBlockIndex != nullptr) {\n\t\t\t\tfor (size_t i = 0; i != localBlockIndex->capacity; ++i) {\n\t\t\t\t\tlocalBlockIndex->index[i]->~BlockIndexEntry();\n\t\t\t\t}\n\t\t\t\tdo {\n\t\t\t\t\tauto prev = localBlockIndex->prev;\n\t\t\t\t\tlocalBlockIndex->~BlockIndexHeader();\n\t\t\t\t\t(Traits::free)(localBlockIndex);\n\t\t\t\t\tlocalBlockIndex = prev;\n\t\t\t\t} while (localBlockIndex != nullptr);\n\t\t\t}\n\t\t}\n\t\t\n\t\ttemplate<AllocationMode allocMode, typename U>\n\t\tinline bool enqueue(U&& element)\n\t\t{\n\t\t\tindex_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tindex_t newTailIndex = 1 + currentTailIndex;\n\t\t\tif ((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n\t\t\t\t// We reached the end of a block, start a new one\n\t\t\t\tauto head = this->headIndex.load(std::memory_order_relaxed);\n\t\t\t\tassert(!details::circular_less_than<index_t>(currentTailIndex, head));\n\t\t\t\tif (!details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\t\t// Find out where we'll be inserting this block in the block index\n\t\t\t\tBlockIndexEntry* idxEntry;\n\t\t\t\tif (!insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Get ahold of a new block\n\t\t\t\tauto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();\n\t\t\t\tif (newBlock == nullptr) {\n\t\t\t\t\trewind_block_index_tail();\n\t\t\t\t\tidxEntry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n#ifdef MCDBGQ_TRACKMEM\n\t\t\t\tnewBlock->owner = this;\n#endif\n\t\t\t\tnewBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>();\n\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {\n\t\t\t\t\t// May throw, try to insert now before we publish the fact that we have this new block\n\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\tnew ((*newBlock)[currentTailIndex]) T(std::forward<U>(element));\n\t\t\t\t\t}\n\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\trewind_block_index_tail();\n\t\t\t\t\t\tidxEntry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\tthis->parent->add_block_to_free_list(newBlock);\n\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Insert the new block into the index\n\t\t\t\tidxEntry->value.store(newBlock, std::memory_order_relaxed);\n\t\t\t\t\n\t\t\t\tthis->tailBlock = newBlock;\n\t\t\t\t\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast<T*>(nullptr)) T(std::forward<U>(element)))) {\n\t\t\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// Enqueue\n\t\t\tnew ((*this->tailBlock)[currentTailIndex]) T(std::forward<U>(element));\n\t\t\t\n\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\ttemplate<typename U>\n\t\tbool dequeue(U& element)\n\t\t{\n\t\t\t// See ExplicitProducer::dequeue for rationale and explanation\n\t\t\tindex_t tail = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tindex_t overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n\t\t\tif (details::circular_less_than<index_t>(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) {\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\t\n\t\t\t\tindex_t myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed);\n\t\t\t\ttail = this->tailIndex.load(std::memory_order_acquire);\n\t\t\t\tif ((details::likely)(details::circular_less_than<index_t>(myDequeueCount - overcommit, tail))) {\n\t\t\t\t\tindex_t index = this->headIndex.fetch_add(1, std::memory_order_acq_rel);\n\t\t\t\t\t\n\t\t\t\t\t// Determine which block the element is in\n\t\t\t\t\tauto entry = get_block_index_entry_for_index(index);\n\t\t\t\t\t\n\t\t\t\t\t// Dequeue\n\t\t\t\t\tauto block = entry->value.load(std::memory_order_relaxed);\n\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\t\n\t\t\t\t\tif (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) {\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\t\t\t// Note: Acquiring the mutex with every dequeue instead of only when a block\n\t\t\t\t\t\t// is released is very sub-optimal, but it is, after all, purely debug code.\n\t\t\t\t\t\tdebug::DebugLock lock(producer->mutex);\n#endif\n\t\t\t\t\t\tstruct Guard {\n\t\t\t\t\t\t\tBlock* block;\n\t\t\t\t\t\t\tindex_t index;\n\t\t\t\t\t\t\tBlockIndexEntry* entry;\n\t\t\t\t\t\t\tConcurrentQueue* parent;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t~Guard()\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t(*block)[index]->~T();\n\t\t\t\t\t\t\t\tif (block->ConcurrentQueue::Block::template set_empty<implicit_context>(index)) {\n\t\t\t\t\t\t\t\t\tentry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\t\t\tparent->add_block_to_free_list(block);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} guard = { block, index, entry, this->parent };\n\n\t\t\t\t\t\telement = std::move(el); // NOLINT\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\telement = std::move(el); // NOLINT\n\t\t\t\t\t\tel.~T(); // NOLINT\n\n\t\t\t\t\t\tif (block->ConcurrentQueue::Block::template set_empty<implicit_context>(index)) {\n\t\t\t\t\t\t\t{\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\t\t\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\t\t\t\t\t\t// Add the block back into the global free pool (and remove from block index)\n\t\t\t\t\t\t\t\tentry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis->parent->add_block_to_free_list(block);\t\t// releases the above store\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis->dequeueOvercommit.fetch_add(1, std::memory_order_release);\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\treturn false;\n\t\t}\n\t\t\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable: 4706)  // assignment within conditional expression\n#endif\n\t\ttemplate<AllocationMode allocMode, typename It>\n\t\tbool enqueue_bulk(It itemFirst, size_t count)\n\t\t{\n\t\t\t// First, we need to make sure we have enough room to enqueue all of the elements;\n\t\t\t// this means pre-allocating blocks and putting them in the block index (but only if\n\t\t\t// all the allocations succeeded).\n\t\t\t\n\t\t\t// Note that the tailBlock we start off with may not be owned by us any more;\n\t\t\t// this happens if it was filled up exactly to the top (setting tailIndex to\n\t\t\t// the first index of the next block which is not yet allocated), then dequeued\n\t\t\t// completely (putting it on the free list) before we enqueue again.\n\t\t\t\n\t\t\tindex_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto startBlock = this->tailBlock;\n\t\t\tBlock* firstAllocatedBlock = nullptr;\n\t\t\tauto endBlock = this->tailBlock;\n\t\t\t\n\t\t\t// Figure out how many blocks we'll need to allocate, and do so\n\t\t\tsize_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));\n\t\t\tindex_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\tif (blockBaseDiff > 0) {\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\t\tdo {\n\t\t\t\t\tblockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\tcurrentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\n\t\t\t\t\t// Find out where we'll be inserting this block in the block index\n\t\t\t\t\tBlockIndexEntry* idxEntry = nullptr;  // initialization here unnecessary but compiler can't always tell\n\t\t\t\t\tBlock* newBlock;\n\t\t\t\t\tbool indexInserted = false;\n\t\t\t\t\tauto head = this->headIndex.load(std::memory_order_relaxed);\n\t\t\t\t\tassert(!details::circular_less_than<index_t>(currentTailIndex, head));\n\t\t\t\t\tbool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));\n\n\t\t\t\t\tif (full || !(indexInserted = insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) || (newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>()) == nullptr) {\n\t\t\t\t\t\t// Index allocation or block allocation failed; revert any other allocations\n\t\t\t\t\t\t// and index insertions done so far for this operation\n\t\t\t\t\t\tif (indexInserted) {\n\t\t\t\t\t\t\trewind_block_index_tail();\n\t\t\t\t\t\t\tidxEntry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcurrentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\t\t\t\tfor (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {\n\t\t\t\t\t\t\tcurrentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\tidxEntry = get_block_index_entry_for_index(currentTailIndex);\n\t\t\t\t\t\t\tidxEntry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\trewind_block_index_tail();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis->parent->add_blocks_to_free_list(firstAllocatedBlock);\n\t\t\t\t\t\tthis->tailBlock = startBlock;\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t\n#ifdef MCDBGQ_TRACKMEM\n\t\t\t\t\tnewBlock->owner = this;\n#endif\n\t\t\t\t\tnewBlock->ConcurrentQueue::Block::template reset_empty<implicit_context>();\n\t\t\t\t\tnewBlock->next = nullptr;\n\t\t\t\t\t\n\t\t\t\t\t// Insert the new block into the index\n\t\t\t\t\tidxEntry->value.store(newBlock, std::memory_order_relaxed);\n\t\t\t\t\t\n\t\t\t\t\t// Store the chain of blocks so that we can undo if later allocations fail,\n\t\t\t\t\t// and so that we can find the blocks when we do the actual enqueueing\n\t\t\t\t\tif ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr) {\n\t\t\t\t\t\tassert(this->tailBlock != nullptr);\n\t\t\t\t\t\tthis->tailBlock->next = newBlock;\n\t\t\t\t\t}\n\t\t\t\t\tthis->tailBlock = newBlock;\n\t\t\t\t\tendBlock = newBlock;\n\t\t\t\t\tfirstAllocatedBlock = firstAllocatedBlock == nullptr ? newBlock : firstAllocatedBlock;\n\t\t\t\t} while (blockBaseDiff > 0);\n\t\t\t}\n\t\t\t\n\t\t\t// Enqueue, one block at a time\n\t\t\tindex_t newTailIndex = startTailIndex + static_cast<index_t>(count);\n\t\t\tcurrentTailIndex = startTailIndex;\n\t\t\tthis->tailBlock = startBlock;\n\t\t\tassert((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0);\n\t\t\tif ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) {\n\t\t\t\tthis->tailBlock = firstAllocatedBlock;\n\t\t\t}\n\t\t\twhile (true) {\n\t\t\t\tindex_t stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\tif (details::circular_less_than<index_t>(newTailIndex, stopIndex)) {\n\t\t\t\t\tstopIndex = newTailIndex;\n\t\t\t\t}\n\t\t\t\tMOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {\n\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\tnew ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\t\tnew ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst));\n\t\t\t\t\t\t\t++currentTailIndex;\n\t\t\t\t\t\t\t++itemFirst;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\tauto constructedStopIndex = currentTailIndex;\n\t\t\t\t\t\tauto lastBlockEnqueued = this->tailBlock;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!details::is_trivially_destructible<T>::value) {\n\t\t\t\t\t\t\tauto block = startBlock;\n\t\t\t\t\t\t\tif ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {\n\t\t\t\t\t\t\t\tblock = firstAllocatedBlock;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcurrentTailIndex = startTailIndex;\n\t\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\t\tstopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\t\tif (details::circular_less_than<index_t>(constructedStopIndex, stopIndex)) {\n\t\t\t\t\t\t\t\t\tstopIndex = constructedStopIndex;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twhile (currentTailIndex != stopIndex) {\n\t\t\t\t\t\t\t\t\t(*block)[currentTailIndex++]->~T();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (block == lastBlockEnqueued) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tblock = block->next;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tcurrentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\t\t\t\tfor (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {\n\t\t\t\t\t\t\tcurrentTailIndex += static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\tauto idxEntry = get_block_index_entry_for_index(currentTailIndex);\n\t\t\t\t\t\t\tidxEntry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\trewind_block_index_tail();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis->parent->add_blocks_to_free_list(firstAllocatedBlock);\n\t\t\t\t\t\tthis->tailBlock = startBlock;\n\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this->tailBlock == endBlock) {\n\t\t\t\t\tassert(currentTailIndex == newTailIndex);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis->tailBlock = this->tailBlock->next;\n\t\t\t}\n\t\t\tthis->tailIndex.store(newTailIndex, std::memory_order_release);\n\t\t\treturn true;\n\t\t}\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\t\t\n\t\ttemplate<typename It>\n\t\tsize_t dequeue_bulk(It& itemFirst, size_t max)\n\t\t{\n\t\t\tauto tail = this->tailIndex.load(std::memory_order_relaxed);\n\t\t\tauto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);\n\t\t\tauto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));\n\t\t\tif (details::circular_less_than<size_t>(0, desiredCount)) {\n\t\t\t\tdesiredCount = desiredCount < max ? desiredCount : max;\n\t\t\t\tstd::atomic_thread_fence(std::memory_order_acquire);\n\t\t\t\t\n\t\t\t\tauto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);\n\t\t\t\t\n\t\t\t\ttail = this->tailIndex.load(std::memory_order_acquire);\n\t\t\t\tauto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));\n\t\t\t\tif (details::circular_less_than<size_t>(0, actualCount)) {\n\t\t\t\t\tactualCount = desiredCount < actualCount ? desiredCount : actualCount;\n\t\t\t\t\tif (actualCount < desiredCount) {\n\t\t\t\t\t\tthis->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get the first index. Note that since there's guaranteed to be at least actualCount elements, this\n\t\t\t\t\t// will never exceed tail.\n\t\t\t\t\tauto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);\n\t\t\t\t\t\n\t\t\t\t\t// Iterate the blocks and dequeue\n\t\t\t\t\tauto index = firstIndex;\n\t\t\t\t\tBlockIndexHeader* localBlockIndex;\n\t\t\t\t\tauto indexIndex = get_block_index_index_for_index(index, localBlockIndex);\n\t\t\t\t\tdo {\n\t\t\t\t\t\tauto blockStartIndex = index;\n\t\t\t\t\t\tindex_t endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\tendIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n\t\t\t\t\t\t\n\t\t\t\t\t\tauto entry = localBlockIndex->index[indexIndex];\n\t\t\t\t\t\tauto block = entry->value.load(std::memory_order_relaxed);\n\t\t\t\t\t\tif (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) {\n\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\t\t\t\t*itemFirst++ = std::move(el);\n\t\t\t\t\t\t\t\tel.~T();\n\t\t\t\t\t\t\t\t++index;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tMOODYCAMEL_TRY {\n\t\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\t\tauto& el = *((*block)[index]);\n\t\t\t\t\t\t\t\t\t*itemFirst = std::move(el);\n\t\t\t\t\t\t\t\t\t++itemFirst;\n\t\t\t\t\t\t\t\t\tel.~T();\n\t\t\t\t\t\t\t\t\t++index;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tMOODYCAMEL_CATCH (...) {\n\t\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t\tentry = localBlockIndex->index[indexIndex];\n\t\t\t\t\t\t\t\t\tblock = entry->value.load(std::memory_order_relaxed);\n\t\t\t\t\t\t\t\t\twhile (index != endIndex) {\n\t\t\t\t\t\t\t\t\t\t(*block)[index++]->~T();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (block->ConcurrentQueue::Block::template set_many_empty<implicit_context>(blockStartIndex, static_cast<size_t>(endIndex - blockStartIndex))) {\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\t\t\t\t\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\t\t\t\t\t\t\t\tentry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\t\t\t\tthis->parent->add_block_to_free_list(block);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tindexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tblockStartIndex = index;\n\t\t\t\t\t\t\t\t\tendIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);\n\t\t\t\t\t\t\t\t\tendIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;\n\t\t\t\t\t\t\t\t} while (index != firstIndex + actualCount);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tMOODYCAMEL_RETHROW;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (block->ConcurrentQueue::Block::template set_many_empty<implicit_context>(blockStartIndex, static_cast<size_t>(endIndex - blockStartIndex))) {\n\t\t\t\t\t\t\t{\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\t\t\t\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\t\t\t\t\t\t// Note that the set_many_empty above did a release, meaning that anybody who acquires the block\n\t\t\t\t\t\t\t\t// we're about to free can use it safely since our writes (and reads!) will have happened-before then.\n\t\t\t\t\t\t\t\tentry->value.store(nullptr, std::memory_order_relaxed);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis->parent->add_block_to_free_list(block);\t\t// releases the above store\n\t\t\t\t\t\t}\n\t\t\t\t\t\tindexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1);\n\t\t\t\t\t} while (index != firstIndex + actualCount);\n\t\t\t\t\t\n\t\t\t\t\treturn actualCount;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn 0;\n\t\t}\n\t\t\n\tprivate:\n\t\t// The block size must be > 1, so any number with the low bit set is an invalid block base index\n\t\tstatic const index_t INVALID_BLOCK_BASE = 1;\n\t\t\n\t\tstruct BlockIndexEntry\n\t\t{\n\t\t\tstd::atomic<index_t> key;\n\t\t\tstd::atomic<Block*> value;\n\t\t};\n\t\t\n\t\tstruct BlockIndexHeader\n\t\t{\n\t\t\tsize_t capacity;\n\t\t\tstd::atomic<size_t> tail;\n\t\t\tBlockIndexEntry* entries;\n\t\t\tBlockIndexEntry** index;\n\t\t\tBlockIndexHeader* prev;\n\t\t};\n\t\t\n\t\ttemplate<AllocationMode allocMode>\n\t\tinline bool insert_block_index_entry(BlockIndexEntry*& idxEntry, index_t blockStartIndex)\n\t\t{\n\t\t\tauto localBlockIndex = blockIndex.load(std::memory_order_relaxed);\t\t// We're the only writer thread, relaxed is OK\n\t\t\tif (localBlockIndex == nullptr) {\n\t\t\t\treturn false;  // this can happen if new_block_index failed in the constructor\n\t\t\t}\n\t\t\tsize_t newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1);\n\t\t\tidxEntry = localBlockIndex->index[newTail];\n\t\t\tif (idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE ||\n\t\t\t\tidxEntry->value.load(std::memory_order_relaxed) == nullptr) {\n\t\t\t\t\n\t\t\t\tidxEntry->key.store(blockStartIndex, std::memory_order_relaxed);\n\t\t\t\tlocalBlockIndex->tail.store(newTail, std::memory_order_release);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t\n\t\t\t// No room in the old block index, try to allocate another one!\n\t\t\tMOODYCAMEL_CONSTEXPR_IF (allocMode == CannotAlloc) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (!new_block_index()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlocalBlockIndex = blockIndex.load(std::memory_order_relaxed);\n\t\t\t\tnewTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1);\n\t\t\t\tidxEntry = localBlockIndex->index[newTail];\n\t\t\t\tassert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE);\n\t\t\t\tidxEntry->key.store(blockStartIndex, std::memory_order_relaxed);\n\t\t\t\tlocalBlockIndex->tail.store(newTail, std::memory_order_release);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tinline void rewind_block_index_tail()\n\t\t{\n\t\t\tauto localBlockIndex = blockIndex.load(std::memory_order_relaxed);\n\t\t\tlocalBlockIndex->tail.store((localBlockIndex->tail.load(std::memory_order_relaxed) - 1) & (localBlockIndex->capacity - 1), std::memory_order_relaxed);\n\t\t}\n\t\t\n\t\tinline BlockIndexEntry* get_block_index_entry_for_index(index_t index) const\n\t\t{\n\t\t\tBlockIndexHeader* localBlockIndex;\n\t\t\tauto idx = get_block_index_index_for_index(index, localBlockIndex);\n\t\t\treturn localBlockIndex->index[idx];\n\t\t}\n\t\t\n\t\tinline size_t get_block_index_index_for_index(index_t index, BlockIndexHeader*& localBlockIndex) const\n\t\t{\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\t\tdebug::DebugLock lock(mutex);\n#endif\n\t\t\tindex &= ~static_cast<index_t>(BLOCK_SIZE - 1);\n\t\t\tlocalBlockIndex = blockIndex.load(std::memory_order_acquire);\n\t\t\tauto tail = localBlockIndex->tail.load(std::memory_order_acquire);\n\t\t\tauto tailBase = localBlockIndex->index[tail]->key.load(std::memory_order_relaxed);\n\t\t\tassert(tailBase != INVALID_BLOCK_BASE);\n\t\t\t// Note: Must use division instead of shift because the index may wrap around, causing a negative\n\t\t\t// offset, whose negativity we want to preserve\n\t\t\tauto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(index - tailBase) / static_cast<typename std::make_signed<index_t>::type>(BLOCK_SIZE));\n\t\t\tsize_t idx = (tail + offset) & (localBlockIndex->capacity - 1);\n\t\t\tassert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr);\n\t\t\treturn idx;\n\t\t}\n\t\t\n\t\tbool new_block_index()\n\t\t{\n\t\t\tauto prev = blockIndex.load(std::memory_order_relaxed);\n\t\t\tsize_t prevCapacity = prev == nullptr ? 0 : prev->capacity;\n\t\t\tauto entryCount = prev == nullptr ? nextBlockIndexCapacity : prevCapacity;\n\t\t\tauto raw = static_cast<char*>((Traits::malloc)(\n\t\t\t\tsizeof(BlockIndexHeader) +\n\t\t\t\tstd::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * entryCount +\n\t\t\t\tstd::alignment_of<BlockIndexEntry*>::value - 1 + sizeof(BlockIndexEntry*) * nextBlockIndexCapacity));\n\t\t\tif (raw == nullptr) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tauto header = new (raw) BlockIndexHeader;\n\t\t\tauto entries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(raw + sizeof(BlockIndexHeader)));\n\t\t\tauto index = reinterpret_cast<BlockIndexEntry**>(details::align_for<BlockIndexEntry*>(reinterpret_cast<char*>(entries) + sizeof(BlockIndexEntry) * entryCount));\n\t\t\tif (prev != nullptr) {\n\t\t\t\tauto prevTail = prev->tail.load(std::memory_order_relaxed);\n\t\t\t\tauto prevPos = prevTail;\n\t\t\t\tsize_t i = 0;\n\t\t\t\tdo {\n\t\t\t\t\tprevPos = (prevPos + 1) & (prev->capacity - 1);\n\t\t\t\t\tindex[i++] = prev->index[prevPos];\n\t\t\t\t} while (prevPos != prevTail);\n\t\t\t\tassert(i == prevCapacity);\n\t\t\t}\n\t\t\tfor (size_t i = 0; i != entryCount; ++i) {\n\t\t\t\tnew (entries + i) BlockIndexEntry;\n\t\t\t\tentries[i].key.store(INVALID_BLOCK_BASE, std::memory_order_relaxed);\n\t\t\t\tindex[prevCapacity + i] = entries + i;\n\t\t\t}\n\t\t\theader->prev = prev;\n\t\t\theader->entries = entries;\n\t\t\theader->index = index;\n\t\t\theader->capacity = nextBlockIndexCapacity;\n\t\t\theader->tail.store((prevCapacity - 1) & (nextBlockIndexCapacity - 1), std::memory_order_relaxed);\n\t\t\t\n\t\t\tblockIndex.store(header, std::memory_order_release);\n\t\t\t\n\t\t\tnextBlockIndexCapacity <<= 1;\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\tprivate:\n\t\tsize_t nextBlockIndexCapacity;\n\t\tstd::atomic<BlockIndexHeader*> blockIndex;\n\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\tpublic:\n\t\tdetails::ThreadExitListener threadExitListener;\n\tprivate:\n#endif\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\tpublic:\n\t\tImplicitProducer* nextImplicitProducer;\n\tprivate:\n#endif\n\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX\n\t\tmutable debug::DebugMutex mutex;\n#endif\n#ifdef MCDBGQ_TRACKMEM\n\t\tfriend struct MemStats;\n#endif\n\t};\n\t\n\t\n\t//////////////////////////////////\n\t// Block pool manipulation\n\t//////////////////////////////////\n\t\n\tvoid populate_initial_block_list(size_t blockCount)\n\t{\n\t\tinitialBlockPoolSize = blockCount;\n\t\tif (initialBlockPoolSize == 0) {\n\t\t\tinitialBlockPool = nullptr;\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tinitialBlockPool = create_array<Block>(blockCount);\n\t\tif (initialBlockPool == nullptr) {\n\t\t\tinitialBlockPoolSize = 0;\n\t\t}\n\t\tfor (size_t i = 0; i < initialBlockPoolSize; ++i) {\n\t\t\tinitialBlockPool[i].dynamicallyAllocated = false;\n\t\t}\n\t}\n\t\n\tinline Block* try_get_block_from_initial_pool()\n\t{\n\t\tif (initialBlockPoolIndex.load(std::memory_order_relaxed) >= initialBlockPoolSize) {\n\t\t\treturn nullptr;\n\t\t}\n\t\t\n\t\tauto index = initialBlockPoolIndex.fetch_add(1, std::memory_order_relaxed);\n\t\t\n\t\treturn index < initialBlockPoolSize ? (initialBlockPool + index) : nullptr;\n\t}\n\t\n\tinline void add_block_to_free_list(Block* block)\n\t{\n#ifdef MCDBGQ_TRACKMEM\n\t\tblock->owner = nullptr;\n#endif\n\t\tif (!Traits::RECYCLE_ALLOCATED_BLOCKS && block->dynamicallyAllocated) {\n\t\t\tdestroy(block);\n\t\t}\n\t\telse {\n\t\t\tfreeList.add(block);\n\t\t}\n\t}\n\t\n\tinline void add_blocks_to_free_list(Block* block)\n\t{\n\t\twhile (block != nullptr) {\n\t\t\tauto next = block->next;\n\t\t\tadd_block_to_free_list(block);\n\t\t\tblock = next;\n\t\t}\n\t}\n\t\n\tinline Block* try_get_block_from_free_list()\n\t{\n\t\treturn freeList.try_get();\n\t}\n\t\n\t// Gets a free block from one of the memory pools, or allocates a new one (if applicable)\n\ttemplate<AllocationMode canAlloc>\n\tBlock* requisition_block()\n\t{\n\t\tauto block = try_get_block_from_initial_pool();\n\t\tif (block != nullptr) {\n\t\t\treturn block;\n\t\t}\n\t\t\n\t\tblock = try_get_block_from_free_list();\n\t\tif (block != nullptr) {\n\t\t\treturn block;\n\t\t}\n\t\t\n\t\tMOODYCAMEL_CONSTEXPR_IF (canAlloc == CanAlloc) {\n\t\t\treturn create<Block>();\n\t\t}\n\t\telse {\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\t\n\n#ifdef MCDBGQ_TRACKMEM\n\tpublic:\n\t\tstruct MemStats {\n\t\t\tsize_t allocatedBlocks;\n\t\t\tsize_t usedBlocks;\n\t\t\tsize_t freeBlocks;\n\t\t\tsize_t ownedBlocksExplicit;\n\t\t\tsize_t ownedBlocksImplicit;\n\t\t\tsize_t implicitProducers;\n\t\t\tsize_t explicitProducers;\n\t\t\tsize_t elementsEnqueued;\n\t\t\tsize_t blockClassBytes;\n\t\t\tsize_t queueClassBytes;\n\t\t\tsize_t implicitBlockIndexBytes;\n\t\t\tsize_t explicitBlockIndexBytes;\n\t\t\t\n\t\t\tfriend class ConcurrentQueue;\n\t\t\t\n\t\tprivate:\n\t\t\tstatic MemStats getFor(ConcurrentQueue* q)\n\t\t\t{\n\t\t\t\tMemStats stats = { 0 };\n\t\t\t\t\n\t\t\t\tstats.elementsEnqueued = q->size_approx();\n\t\t\t\n\t\t\t\tauto block = q->freeList.head_unsafe();\n\t\t\t\twhile (block != nullptr) {\n\t\t\t\t\t++stats.allocatedBlocks;\n\t\t\t\t\t++stats.freeBlocks;\n\t\t\t\t\tblock = block->freeListNext.load(std::memory_order_relaxed);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfor (auto ptr = q->producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\t\t\tbool implicit = dynamic_cast<ImplicitProducer*>(ptr) != nullptr;\n\t\t\t\t\tstats.implicitProducers += implicit ? 1 : 0;\n\t\t\t\t\tstats.explicitProducers += implicit ? 0 : 1;\n\t\t\t\t\t\n\t\t\t\t\tif (implicit) {\n\t\t\t\t\t\tauto prod = static_cast<ImplicitProducer*>(ptr);\n\t\t\t\t\t\tstats.queueClassBytes += sizeof(ImplicitProducer);\n\t\t\t\t\t\tauto head = prod->headIndex.load(std::memory_order_relaxed);\n\t\t\t\t\t\tauto tail = prod->tailIndex.load(std::memory_order_relaxed);\n\t\t\t\t\t\tauto hash = prod->blockIndex.load(std::memory_order_relaxed);\n\t\t\t\t\t\tif (hash != nullptr) {\n\t\t\t\t\t\t\tfor (size_t i = 0; i != hash->capacity; ++i) {\n\t\t\t\t\t\t\t\tif (hash->index[i]->key.load(std::memory_order_relaxed) != ImplicitProducer::INVALID_BLOCK_BASE && hash->index[i]->value.load(std::memory_order_relaxed) != nullptr) {\n\t\t\t\t\t\t\t\t\t++stats.allocatedBlocks;\n\t\t\t\t\t\t\t\t\t++stats.ownedBlocksImplicit;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstats.implicitBlockIndexBytes += hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry);\n\t\t\t\t\t\t\tfor (; hash != nullptr; hash = hash->prev) {\n\t\t\t\t\t\t\t\tstats.implicitBlockIndexBytes += sizeof(typename ImplicitProducer::BlockIndexHeader) + hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry*);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (; details::circular_less_than<index_t>(head, tail); head += BLOCK_SIZE) {\n\t\t\t\t\t\t\t//auto block = prod->get_block_index_entry_for_index(head);\n\t\t\t\t\t\t\t++stats.usedBlocks;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tauto prod = static_cast<ExplicitProducer*>(ptr);\n\t\t\t\t\t\tstats.queueClassBytes += sizeof(ExplicitProducer);\n\t\t\t\t\t\tauto tailBlock = prod->tailBlock;\n\t\t\t\t\t\tbool wasNonEmpty = false;\n\t\t\t\t\t\tif (tailBlock != nullptr) {\n\t\t\t\t\t\t\tauto block = tailBlock;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t++stats.allocatedBlocks;\n\t\t\t\t\t\t\t\tif (!block->ConcurrentQueue::Block::template is_empty<explicit_context>() || wasNonEmpty) {\n\t\t\t\t\t\t\t\t\t++stats.usedBlocks;\n\t\t\t\t\t\t\t\t\twasNonEmpty = wasNonEmpty || block != tailBlock;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t++stats.ownedBlocksExplicit;\n\t\t\t\t\t\t\t\tblock = block->next;\n\t\t\t\t\t\t\t} while (block != tailBlock);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tauto index = prod->blockIndex.load(std::memory_order_relaxed);\n\t\t\t\t\t\twhile (index != nullptr) {\n\t\t\t\t\t\t\tstats.explicitBlockIndexBytes += sizeof(typename ExplicitProducer::BlockIndexHeader) + index->size * sizeof(typename ExplicitProducer::BlockIndexEntry);\n\t\t\t\t\t\t\tindex = static_cast<typename ExplicitProducer::BlockIndexHeader*>(index->prev);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tauto freeOnInitialPool = q->initialBlockPoolIndex.load(std::memory_order_relaxed) >= q->initialBlockPoolSize ? 0 : q->initialBlockPoolSize - q->initialBlockPoolIndex.load(std::memory_order_relaxed);\n\t\t\t\tstats.allocatedBlocks += freeOnInitialPool;\n\t\t\t\tstats.freeBlocks += freeOnInitialPool;\n\t\t\t\t\n\t\t\t\tstats.blockClassBytes = sizeof(Block) * stats.allocatedBlocks;\n\t\t\t\tstats.queueClassBytes += sizeof(ConcurrentQueue);\n\t\t\t\t\n\t\t\t\treturn stats;\n\t\t\t}\n\t\t};\n\t\t\n\t\t// For debugging only. Not thread-safe.\n\t\tMemStats getMemStats()\n\t\t{\n\t\t\treturn MemStats::getFor(this);\n\t\t}\n\tprivate:\n\t\tfriend struct MemStats;\n#endif\n\t\n\t\n\t//////////////////////////////////\n\t// Producer list manipulation\n\t//////////////////////////////////\t\n\t\n\tProducerBase* recycle_or_create_producer(bool isExplicit)\n\t{\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n\t\tdebug::DebugLock lock(implicitProdMutex);\n#endif\n\t\t// Try to re-use one first\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tif (ptr->inactive.load(std::memory_order_relaxed) && ptr->isExplicit == isExplicit) {\n\t\t\t\tbool expected = true;\n\t\t\t\tif (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) {\n\t\t\t\t\t// We caught one! It's been marked as activated, the caller can have it\n\t\t\t\t\treturn ptr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn add_producer(isExplicit ? static_cast<ProducerBase*>(create<ExplicitProducer>(this)) : create<ImplicitProducer>(this));\n\t}\n\t\n\tProducerBase* add_producer(ProducerBase* producer)\n\t{\n\t\t// Handle failed memory allocation\n\t\tif (producer == nullptr) {\n\t\t\treturn nullptr;\n\t\t}\n\t\t\n\t\tproducerCount.fetch_add(1, std::memory_order_relaxed);\n\t\t\n\t\t// Add it to the lock-free list\n\t\tauto prevTail = producerListTail.load(std::memory_order_relaxed);\n\t\tdo {\n\t\t\tproducer->next = prevTail;\n\t\t} while (!producerListTail.compare_exchange_weak(prevTail, producer, std::memory_order_release, std::memory_order_relaxed));\n\t\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\t\tif (producer->isExplicit) {\n\t\t\tauto prevTailExplicit = explicitProducers.load(std::memory_order_relaxed);\n\t\t\tdo {\n\t\t\t\tstatic_cast<ExplicitProducer*>(producer)->nextExplicitProducer = prevTailExplicit;\n\t\t\t} while (!explicitProducers.compare_exchange_weak(prevTailExplicit, static_cast<ExplicitProducer*>(producer), std::memory_order_release, std::memory_order_relaxed));\n\t\t}\n\t\telse {\n\t\t\tauto prevTailImplicit = implicitProducers.load(std::memory_order_relaxed);\n\t\t\tdo {\n\t\t\t\tstatic_cast<ImplicitProducer*>(producer)->nextImplicitProducer = prevTailImplicit;\n\t\t\t} while (!implicitProducers.compare_exchange_weak(prevTailImplicit, static_cast<ImplicitProducer*>(producer), std::memory_order_release, std::memory_order_relaxed));\n\t\t}\n#endif\n\t\t\n\t\treturn producer;\n\t}\n\t\n\tvoid reown_producers()\n\t{\n\t\t// After another instance is moved-into/swapped-with this one, all the\n\t\t// producers we stole still think their parents are the other queue.\n\t\t// So fix them up!\n\t\tfor (auto ptr = producerListTail.load(std::memory_order_relaxed); ptr != nullptr; ptr = ptr->next_prod()) {\n\t\t\tptr->parent = this;\n\t\t}\n\t}\n\t\n\t\n\t//////////////////////////////////\n\t// Implicit producer hash\n\t//////////////////////////////////\n\t\n\tstruct ImplicitProducerKVP\n\t{\n\t\tstd::atomic<details::thread_id_t> key;\n\t\tImplicitProducer* value;\t\t// No need for atomicity since it's only read by the thread that sets it in the first place\n\t\t\n\t\tImplicitProducerKVP() : value(nullptr) { }\n\t\t\n\t\tImplicitProducerKVP(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT\n\t\t{\n\t\t\tkey.store(other.key.load(std::memory_order_relaxed), std::memory_order_relaxed);\n\t\t\tvalue = other.value;\n\t\t}\n\t\t\n\t\tinline ImplicitProducerKVP& operator=(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT\n\t\t{\n\t\t\tswap(other);\n\t\t\treturn *this;\n\t\t}\n\t\t\n\t\tinline void swap(ImplicitProducerKVP& other) MOODYCAMEL_NOEXCEPT\n\t\t{\n\t\t\tif (this != &other) {\n\t\t\t\tdetails::swap_relaxed(key, other.key);\n\t\t\t\tstd::swap(value, other.value);\n\t\t\t}\n\t\t}\n\t};\n\t\n\ttemplate<typename XT, typename XTraits>\n\tfriend void moodycamel::swap(typename ConcurrentQueue<XT, XTraits>::ImplicitProducerKVP&, typename ConcurrentQueue<XT, XTraits>::ImplicitProducerKVP&) MOODYCAMEL_NOEXCEPT;\n\t\n\tstruct ImplicitProducerHash\n\t{\n\t\tsize_t capacity;\n\t\tImplicitProducerKVP* entries;\n\t\tImplicitProducerHash* prev;\n\t};\n\t\n\tinline void populate_initial_implicit_producer_hash()\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) {\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\timplicitProducerHashCount.store(0, std::memory_order_relaxed);\n\t\t\tauto hash = &initialImplicitProducerHash;\n\t\t\thash->capacity = INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;\n\t\t\thash->entries = &initialImplicitProducerHashEntries[0];\n\t\t\tfor (size_t i = 0; i != INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; ++i) {\n\t\t\t\tinitialImplicitProducerHashEntries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed);\n\t\t\t}\n\t\t\thash->prev = nullptr;\n\t\t\timplicitProducerHash.store(hash, std::memory_order_relaxed);\n\t\t}\n\t}\n\t\n\tvoid swap_implicit_producer_hashes(ConcurrentQueue& other)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) {\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\t// Swap (assumes our implicit producer hash is initialized)\n\t\t\tinitialImplicitProducerHashEntries.swap(other.initialImplicitProducerHashEntries);\n\t\t\tinitialImplicitProducerHash.entries = &initialImplicitProducerHashEntries[0];\n\t\t\tother.initialImplicitProducerHash.entries = &other.initialImplicitProducerHashEntries[0];\n\t\t\t\n\t\t\tdetails::swap_relaxed(implicitProducerHashCount, other.implicitProducerHashCount);\n\t\t\t\n\t\t\tdetails::swap_relaxed(implicitProducerHash, other.implicitProducerHash);\n\t\t\tif (implicitProducerHash.load(std::memory_order_relaxed) == &other.initialImplicitProducerHash) {\n\t\t\t\timplicitProducerHash.store(&initialImplicitProducerHash, std::memory_order_relaxed);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tImplicitProducerHash* hash;\n\t\t\t\tfor (hash = implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &other.initialImplicitProducerHash; hash = hash->prev) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\thash->prev = &initialImplicitProducerHash;\n\t\t\t}\n\t\t\tif (other.implicitProducerHash.load(std::memory_order_relaxed) == &initialImplicitProducerHash) {\n\t\t\t\tother.implicitProducerHash.store(&other.initialImplicitProducerHash, std::memory_order_relaxed);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tImplicitProducerHash* hash;\n\t\t\t\tfor (hash = other.implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &initialImplicitProducerHash; hash = hash->prev) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\thash->prev = &other.initialImplicitProducerHash;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Only fails (returns nullptr) if memory allocation fails\n\tImplicitProducer* get_or_add_implicit_producer()\n\t{\n\t\t// Note that since the data is essentially thread-local (key is thread ID),\n\t\t// there's a reduced need for fences (memory ordering is already consistent\n\t\t// for any individual thread), except for the current table itself.\n\t\t\n\t\t// Start by looking for the thread ID in the current and all previous hash tables.\n\t\t// If it's not found, it must not be in there yet, since this same thread would\n\t\t// have added it previously to one of the tables that we traversed.\n\t\t\n\t\t// Code and algorithm adapted from http://preshing.com/20130605/the-worlds-simplest-lock-free-hash-table\n\t\t\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n\t\tdebug::DebugLock lock(implicitProdMutex);\n#endif\n\t\t\n\t\tauto id = details::thread_id();\n\t\tauto hashedId = details::hash_thread_id(id);\n\t\t\n\t\tauto mainHash = implicitProducerHash.load(std::memory_order_acquire);\n\t\tassert(mainHash != nullptr);  // silence clang-tidy and MSVC warnings (hash cannot be null)\n\t\tfor (auto hash = mainHash; hash != nullptr; hash = hash->prev) {\n\t\t\t// Look for the id in this hash\n\t\t\tauto index = hashedId;\n\t\t\twhile (true) {\t\t// Not an infinite loop because at least one slot is free in the hash table\n\t\t\t\tindex &= hash->capacity - 1u;\n\t\t\t\t\n\t\t\t\tauto probedKey = hash->entries[index].key.load(std::memory_order_relaxed);\n\t\t\t\tif (probedKey == id) {\n\t\t\t\t\t// Found it! If we had to search several hashes deep, though, we should lazily add it\n\t\t\t\t\t// to the current main hash table to avoid the extended search next time.\n\t\t\t\t\t// Note there's guaranteed to be room in the current hash table since every subsequent\n\t\t\t\t\t// table implicitly reserves space for all previous tables (there's only one\n\t\t\t\t\t// implicitProducerHashCount).\n\t\t\t\t\tauto value = hash->entries[index].value;\n\t\t\t\t\tif (hash != mainHash) {\n\t\t\t\t\t\tindex = hashedId;\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tindex &= mainHash->capacity - 1u;\n\t\t\t\t\t\t\tauto empty = details::invalid_thread_id;\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\t\t\t\t\t\t\tauto reusable = details::invalid_thread_id2;\n\t\t\t\t\t\t\tif (mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_seq_cst, std::memory_order_relaxed) ||\n\t\t\t\t\t\t\t\tmainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_seq_cst, std::memory_order_relaxed)) {\n#else\n\t\t\t\t\t\t\tif (mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_seq_cst, std::memory_order_relaxed)) {\n#endif\n\t\t\t\t\t\t\t\tmainHash->entries[index].value = value;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++index;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t\tif (probedKey == details::invalid_thread_id) {\n\t\t\t\t\tbreak;\t\t// Not in this hash table\n\t\t\t\t}\n\t\t\t\t++index;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Insert!\n\t\tauto newCount = 1 + implicitProducerHashCount.fetch_add(1, std::memory_order_relaxed);\n\t\twhile (true) {\n\t\t\t// NOLINTNEXTLINE(clang-analyzer-core.NullDereference)\n\t\t\tif (newCount >= (mainHash->capacity >> 1) && !implicitProducerHashResizeInProgress.test_and_set(std::memory_order_acquire)) {\n\t\t\t\t// We've acquired the resize lock, try to allocate a bigger hash table.\n\t\t\t\t// Note the acquire fence synchronizes with the release fence at the end of this block, and hence when\n\t\t\t\t// we reload implicitProducerHash it must be the most recent version (it only gets changed within this\n\t\t\t\t// locked block).\n\t\t\t\tmainHash = implicitProducerHash.load(std::memory_order_acquire);\n\t\t\t\tif (newCount >= (mainHash->capacity >> 1)) {\n\t\t\t\t\tsize_t newCapacity = mainHash->capacity << 1;\n\t\t\t\t\twhile (newCount >= (newCapacity >> 1)) {\n\t\t\t\t\t\tnewCapacity <<= 1;\n\t\t\t\t\t}\n\t\t\t\t\tauto raw = static_cast<char*>((Traits::malloc)(sizeof(ImplicitProducerHash) + std::alignment_of<ImplicitProducerKVP>::value - 1 + sizeof(ImplicitProducerKVP) * newCapacity));\n\t\t\t\t\tif (raw == nullptr) {\n\t\t\t\t\t\t// Allocation failed\n\t\t\t\t\t\timplicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);\n\t\t\t\t\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_relaxed);\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tauto newHash = new (raw) ImplicitProducerHash;\n\t\t\t\t\tnewHash->capacity = static_cast<size_t>(newCapacity);\n\t\t\t\t\tnewHash->entries = reinterpret_cast<ImplicitProducerKVP*>(details::align_for<ImplicitProducerKVP>(raw + sizeof(ImplicitProducerHash)));\n\t\t\t\t\tfor (size_t i = 0; i != newCapacity; ++i) {\n\t\t\t\t\t\tnew (newHash->entries + i) ImplicitProducerKVP;\n\t\t\t\t\t\tnewHash->entries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed);\n\t\t\t\t\t}\n\t\t\t\t\tnewHash->prev = mainHash;\n\t\t\t\t\timplicitProducerHash.store(newHash, std::memory_order_release);\n\t\t\t\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_release);\n\t\t\t\t\tmainHash = newHash;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\timplicitProducerHashResizeInProgress.clear(std::memory_order_release);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// If it's < three-quarters full, add to the old one anyway so that we don't have to wait for the next table\n\t\t\t// to finish being allocated by another thread (and if we just finished allocating above, the condition will\n\t\t\t// always be true)\n\t\t\tif (newCount < (mainHash->capacity >> 1) + (mainHash->capacity >> 2)) {\n\t\t\t\tauto producer = static_cast<ImplicitProducer*>(recycle_or_create_producer(false));\n\t\t\t\tif (producer == nullptr) {\n\t\t\t\t\timplicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);\n\t\t\t\t\treturn nullptr;\n\t\t\t\t}\n\t\t\t\t\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\t\t\t\tproducer->threadExitListener.callback = &ConcurrentQueue::implicit_producer_thread_exited_callback;\n\t\t\t\tproducer->threadExitListener.userData = producer;\n\t\t\t\tdetails::ThreadExitNotifier::subscribe(&producer->threadExitListener);\n#endif\n\t\t\t\t\n\t\t\t\tauto index = hashedId;\n\t\t\t\twhile (true) {\n\t\t\t\t\tindex &= mainHash->capacity - 1u;\n\t\t\t\t\tauto empty = details::invalid_thread_id;\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\t\t\t\t\tauto reusable = details::invalid_thread_id2;\n\t\t\t\t\tif (mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_seq_cst, std::memory_order_relaxed)) {\n\t\t\t\t\t\timplicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed);  // already counted as a used slot\n\t\t\t\t\t\tmainHash->entries[index].value = producer;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tif (mainHash->entries[index].key.compare_exchange_strong(empty,    id, std::memory_order_seq_cst, std::memory_order_relaxed)) {\n\t\t\t\t\t\tmainHash->entries[index].value = producer;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t++index;\n\t\t\t\t}\n\t\t\t\treturn producer;\n\t\t\t}\n\t\t\t\n\t\t\t// Hmm, the old hash is quite full and somebody else is busy allocating a new one.\n\t\t\t// We need to wait for the allocating thread to finish (if it succeeds, we add, if not,\n\t\t\t// we try to allocate ourselves).\n\t\t\tmainHash = implicitProducerHash.load(std::memory_order_acquire);\n\t\t}\n\t}\n\t\n#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED\n\tvoid implicit_producer_thread_exited(ImplicitProducer* producer)\n\t{\n\t\t// Remove from hash\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n\t\tdebug::DebugLock lock(implicitProdMutex);\n#endif\n\t\tauto hash = implicitProducerHash.load(std::memory_order_acquire);\n\t\tassert(hash != nullptr);\t\t// The thread exit listener is only registered if we were added to a hash in the first place\n\t\tauto id = details::thread_id();\n\t\tauto hashedId = details::hash_thread_id(id);\n\t\tdetails::thread_id_t probedKey;\n\t\t\n\t\t// We need to traverse all the hashes just in case other threads aren't on the current one yet and are\n\t\t// trying to add an entry thinking there's a free slot (because they reused a producer)\n\t\tfor (; hash != nullptr; hash = hash->prev) {\n\t\t\tauto index = hashedId;\n\t\t\tdo {\n\t\t\t\tindex &= hash->capacity - 1u;\n\t\t\t\tprobedKey = id;\n\t\t\t\tif (hash->entries[index].key.compare_exchange_strong(probedKey, details::invalid_thread_id2, std::memory_order_seq_cst, std::memory_order_relaxed)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t++index;\n\t\t\t} while (probedKey != details::invalid_thread_id);\t\t// Can happen if the hash has changed but we weren't put back in it yet, or if we weren't added to this hash in the first place\n\t\t}\n\t\t\n\t\t// Mark the queue as being recyclable\n\t\tproducer->inactive.store(true, std::memory_order_release);\n\t}\n\t\n\tstatic void implicit_producer_thread_exited_callback(void* userData)\n\t{\n\t\tauto producer = static_cast<ImplicitProducer*>(userData);\n\t\tauto queue = producer->parent;\n\t\tqueue->implicit_producer_thread_exited(producer);\n\t}\n#endif\n\t\n\t//////////////////////////////////\n\t// Utility functions\n\t//////////////////////////////////\n\n\ttemplate<typename TAlign>\n\tstatic inline void* aligned_malloc(size_t size)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (std::alignment_of<TAlign>::value <= std::alignment_of<details::max_align_t>::value)\n\t\t\treturn (Traits::malloc)(size);\n\t\telse {\n\t\t\tsize_t alignment = std::alignment_of<TAlign>::value;\n\t\t\tvoid* raw = (Traits::malloc)(size + alignment - 1 + sizeof(void*));\n\t\t\tif (!raw)\n\t\t\t\treturn nullptr;\n\t\t\tchar* ptr = details::align_for<TAlign>(reinterpret_cast<char*>(raw) + sizeof(void*));\n\t\t\t*(reinterpret_cast<void**>(ptr) - 1) = raw;\n\t\t\treturn ptr;\n\t\t}\n\t}\n\n\ttemplate<typename TAlign>\n\tstatic inline void aligned_free(void* ptr)\n\t{\n\t\tMOODYCAMEL_CONSTEXPR_IF (std::alignment_of<TAlign>::value <= std::alignment_of<details::max_align_t>::value)\n\t\t\treturn (Traits::free)(ptr);\n\t\telse\n\t\t\t(Traits::free)(ptr ? *(reinterpret_cast<void**>(ptr) - 1) : nullptr);\n\t}\n\n\ttemplate<typename U>\n\tstatic inline U* create_array(size_t count)\n\t{\n\t\tassert(count > 0);\n\t\tU* p = static_cast<U*>(aligned_malloc<U>(sizeof(U) * count));\n\t\tif (p == nullptr)\n\t\t\treturn nullptr;\n\n\t\tfor (size_t i = 0; i != count; ++i)\n\t\t\tnew (p + i) U();\n\t\treturn p;\n\t}\n\n\ttemplate<typename U>\n\tstatic inline void destroy_array(U* p, size_t count)\n\t{\n\t\tif (p != nullptr) {\n\t\t\tassert(count > 0);\n\t\t\tfor (size_t i = count; i != 0; )\n\t\t\t\t(p + --i)->~U();\n\t\t}\n\t\taligned_free<U>(p);\n\t}\n\n\ttemplate<typename U>\n\tstatic inline U* create()\n\t{\n\t\tvoid* p = aligned_malloc<U>(sizeof(U));\n\t\treturn p != nullptr ? new (p) U : nullptr;\n\t}\n\n\ttemplate<typename U, typename A1>\n\tstatic inline U* create(A1&& a1)\n\t{\n\t\tvoid* p = aligned_malloc<U>(sizeof(U));\n\t\treturn p != nullptr ? new (p) U(std::forward<A1>(a1)) : nullptr;\n\t}\n\n\ttemplate<typename U>\n\tstatic inline void destroy(U* p)\n\t{\n\t\tif (p != nullptr)\n\t\t\tp->~U();\n\t\taligned_free<U>(p);\n\t}\n\nprivate:\n\tstd::atomic<ProducerBase*> producerListTail;\n\tstd::atomic<std::uint32_t> producerCount;\n\t\n\tstd::atomic<size_t> initialBlockPoolIndex;\n\tBlock* initialBlockPool;\n\tsize_t initialBlockPoolSize;\n\t\n#ifndef MCDBGQ_USEDEBUGFREELIST\n\tFreeList<Block> freeList;\n#else\n\tdebug::DebugFreeList<Block> freeList;\n#endif\n\t\n\tstd::atomic<ImplicitProducerHash*> implicitProducerHash;\n\tstd::atomic<size_t> implicitProducerHashCount;\t\t// Number of slots logically used\n\tImplicitProducerHash initialImplicitProducerHash;\n\tstd::array<ImplicitProducerKVP, INITIAL_IMPLICIT_PRODUCER_HASH_SIZE> initialImplicitProducerHashEntries;\n\tstd::atomic_flag implicitProducerHashResizeInProgress;\n\t\n\tstd::atomic<std::uint32_t> nextExplicitConsumerId;\n\tstd::atomic<std::uint32_t> globalExplicitConsumerOffset;\n\t\n#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH\n\tdebug::DebugMutex implicitProdMutex;\n#endif\n\t\n#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG\n\tstd::atomic<ExplicitProducer*> explicitProducers;\n\tstd::atomic<ImplicitProducer*> implicitProducers;\n#endif\n};\n\n\ntemplate<typename T, typename Traits>\nProducerToken::ProducerToken(ConcurrentQueue<T, Traits>& queue)\n\t: producer(queue.recycle_or_create_producer(true))\n{\n\tif (producer != nullptr) {\n\t\tproducer->token = this;\n\t}\n}\n\ntemplate<typename T, typename Traits>\nProducerToken::ProducerToken(BlockingConcurrentQueue<T, Traits>& queue)\n\t: producer(reinterpret_cast<ConcurrentQueue<T, Traits>*>(&queue)->recycle_or_create_producer(true))\n{\n\tif (producer != nullptr) {\n\t\tproducer->token = this;\n\t}\n}\n\ntemplate<typename T, typename Traits>\nConsumerToken::ConsumerToken(ConcurrentQueue<T, Traits>& queue)\n\t: itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr)\n{\n\tinitialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release);\n\tlastKnownGlobalOffset = static_cast<std::uint32_t>(-1);\n}\n\ntemplate<typename T, typename Traits>\nConsumerToken::ConsumerToken(BlockingConcurrentQueue<T, Traits>& queue)\n\t: itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr)\n{\n\tinitialOffset = reinterpret_cast<ConcurrentQueue<T, Traits>*>(&queue)->nextExplicitConsumerId.fetch_add(1, std::memory_order_release);\n\tlastKnownGlobalOffset = static_cast<std::uint32_t>(-1);\n}\n\ntemplate<typename T, typename Traits>\ninline void swap(ConcurrentQueue<T, Traits>& a, ConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT\n{\n\ta.swap(b);\n}\n\ninline void swap(ProducerToken& a, ProducerToken& b) MOODYCAMEL_NOEXCEPT\n{\n\ta.swap(b);\n}\n\ninline void swap(ConsumerToken& a, ConsumerToken& b) MOODYCAMEL_NOEXCEPT\n{\n\ta.swap(b);\n}\n\ntemplate<typename T, typename Traits>\ninline void swap(typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& a, typename ConcurrentQueue<T, Traits>::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT\n{\n\ta.swap(b);\n}\n\n}\n\n#if defined(_MSC_VER) && (!defined(_HAS_CXX17) || !_HAS_CXX17)\n#pragma warning(pop)\n#endif\n\n#if defined(__GNUC__) && !defined(__INTEL_COMPILER)\n#pragma GCC diagnostic pop\n#endif\n"
  },
  {
    "path": "dispenso/third-party/moodycamel/lightweightsemaphore.h",
    "content": "// Provides an efficient implementation of a semaphore (LightweightSemaphore).\n// This is an extension of Jeff Preshing's sempahore implementation (licensed \n// under the terms of its separate zlib license) that has been adapted and\n// extended by Cameron Desrochers.\n\n#pragma once\n\n#include <cstddef> // For std::size_t\n#include <atomic>\n#include <type_traits> // For std::make_signed<T>\n\n#if defined(_WIN32)\n// Avoid including windows.h in a header; we only need a handful of\n// items, so we'll redeclare them here (this is relatively safe since\n// the API generally has to remain stable between Windows versions).\n// I know this is an ugly hack but it still beats polluting the global\n// namespace with thousands of generic names or adding a .cpp for nothing.\nextern \"C\" {\n\tstruct _SECURITY_ATTRIBUTES;\n\t__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);\n\t__declspec(dllimport) int __stdcall CloseHandle(void* hObject);\n\t__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);\n\t__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);\n}\n#elif defined(__MACH__)\n#include <mach/mach.h>\n#elif defined(__unix__)\n#include <semaphore.h>\n\n#if defined(__GLIBC_PREREQ) && defined(_GNU_SOURCE)\n#if __GLIBC_PREREQ(2,30)\n#define MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC\n#endif\n#endif\n#endif\n\nnamespace moodycamel\n{\nnamespace details\n{\n\n// Code in the mpmc_sema namespace below is an adaptation of Jeff Preshing's\n// portable + lightweight semaphore implementations, originally from\n// https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h\n// LICENSE:\n// Copyright (c) 2015 Jeff Preshing\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//\tclaim that you wrote the original software. If you use this software\n//\tin a product, an acknowledgement in the product documentation would be\n//\tappreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//\tmisrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n#if defined(_WIN32)\nclass Semaphore\n{\nprivate:\n\tvoid* m_hSema;\n\t\n\tSemaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\tSemaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\npublic:\n\tSemaphore(int initialCount = 0)\n\t{\n\t\tassert(initialCount >= 0);\n\t\tconst long maxLong = 0x7fffffff;\n\t\tm_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);\n\t\tassert(m_hSema);\n\t}\n\n\t~Semaphore()\n\t{\n\t\tCloseHandle(m_hSema);\n\t}\n\n\tbool wait()\n\t{\n\t\tconst unsigned long infinite = 0xffffffff;\n\t\treturn WaitForSingleObject(m_hSema, infinite) == 0;\n\t}\n\t\n\tbool try_wait()\n\t{\n\t\treturn WaitForSingleObject(m_hSema, 0) == 0;\n\t}\n\t\n\tbool timed_wait(std::uint64_t usecs)\n\t{\n\t\treturn WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0;\n\t}\n\n\tvoid signal(int count = 1)\n\t{\n\t\twhile (!ReleaseSemaphore(m_hSema, count, nullptr));\n\t}\n};\n#elif defined(__MACH__)\n//---------------------------------------------------------\n// Semaphore (Apple iOS and OSX)\n// Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html\n//---------------------------------------------------------\nclass Semaphore\n{\nprivate:\n\tsemaphore_t m_sema;\n\n\tSemaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\tSemaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\npublic:\n\tSemaphore(int initialCount = 0)\n\t{\n\t\tassert(initialCount >= 0);\n\t\tkern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);\n\t\tassert(rc == KERN_SUCCESS);\n\t\t(void)rc;\n\t}\n\n\t~Semaphore()\n\t{\n\t\tsemaphore_destroy(mach_task_self(), m_sema);\n\t}\n\n\tbool wait()\n\t{\n\t\treturn semaphore_wait(m_sema) == KERN_SUCCESS;\n\t}\n\t\n\tbool try_wait()\n\t{\n\t\treturn timed_wait(0);\n\t}\n\t\n\tbool timed_wait(std::uint64_t timeout_usecs)\n\t{\n\t\tmach_timespec_t ts;\n\t\tts.tv_sec = static_cast<unsigned int>(timeout_usecs / 1000000);\n\t\tts.tv_nsec = static_cast<int>((timeout_usecs % 1000000) * 1000);\n\n\t\t// added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html\n\t\tkern_return_t rc = semaphore_timedwait(m_sema, ts);\n\t\treturn rc == KERN_SUCCESS;\n\t}\n\n\tvoid signal()\n\t{\n\t\twhile (semaphore_signal(m_sema) != KERN_SUCCESS);\n\t}\n\n\tvoid signal(int count)\n\t{\n\t\twhile (count-- > 0)\n\t\t{\n\t\t\twhile (semaphore_signal(m_sema) != KERN_SUCCESS);\n\t\t}\n\t}\n};\n#elif defined(__unix__)\n//---------------------------------------------------------\n// Semaphore (POSIX, Linux)\n//---------------------------------------------------------\nclass Semaphore\n{\nprivate:\n\tsem_t m_sema;\n\n\tSemaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\tSemaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;\n\npublic:\n\tSemaphore(int initialCount = 0)\n\t{\n\t\tassert(initialCount >= 0);\n\t\tint rc = sem_init(&m_sema, 0, static_cast<unsigned int>(initialCount));\n\t\tassert(rc == 0);\n\t\t(void)rc;\n\t}\n\n\t~Semaphore()\n\t{\n\t\tsem_destroy(&m_sema);\n\t}\n\n\tbool wait()\n\t{\n\t\t// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error\n\t\tint rc;\n\t\tdo {\n\t\t\trc = sem_wait(&m_sema);\n\t\t} while (rc == -1 && errno == EINTR);\n\t\treturn rc == 0;\n\t}\n\n\tbool try_wait()\n\t{\n\t\tint rc;\n\t\tdo {\n\t\t\trc = sem_trywait(&m_sema);\n\t\t} while (rc == -1 && errno == EINTR);\n\t\treturn rc == 0;\n\t}\n\n\tbool timed_wait(std::uint64_t usecs)\n\t{\n\t\tstruct timespec ts;\n\t\tconst int usecs_in_1_sec = 1000000;\n\t\tconst int nsecs_in_1_sec = 1000000000;\n#ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC\n\t\tclock_gettime(CLOCK_MONOTONIC, &ts);\n#else\n\t\tclock_gettime(CLOCK_REALTIME, &ts);\n#endif\n\t\tts.tv_sec += (time_t)(usecs / usecs_in_1_sec);\n\t\tts.tv_nsec += (long)(usecs % usecs_in_1_sec) * 1000;\n\t\t// sem_timedwait bombs if you have more than 1e9 in tv_nsec\n\t\t// so we have to clean things up before passing it in\n\t\tif (ts.tv_nsec >= nsecs_in_1_sec) {\n\t\t\tts.tv_nsec -= nsecs_in_1_sec;\n\t\t\t++ts.tv_sec;\n\t\t}\n\n\t\tint rc;\n\t\tdo {\n#ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC\n\t\t\trc = sem_clockwait(&m_sema, CLOCK_MONOTONIC, &ts);\n#else\n\t\t\trc = sem_timedwait(&m_sema, &ts);\n#endif\n\t\t} while (rc == -1 && errno == EINTR);\n\t\treturn rc == 0;\n\t}\n\n\tvoid signal()\n\t{\n\t\twhile (sem_post(&m_sema) == -1);\n\t}\n\n\tvoid signal(int count)\n\t{\n\t\twhile (count-- > 0)\n\t\t{\n\t\t\twhile (sem_post(&m_sema) == -1);\n\t\t}\n\t}\n};\n#else\n#error Unsupported platform! (No semaphore wrapper available)\n#endif\n\n}\t// end namespace details\n\n\n//---------------------------------------------------------\n// LightweightSemaphore\n//---------------------------------------------------------\nclass LightweightSemaphore\n{\npublic:\n\ttypedef std::make_signed<std::size_t>::type ssize_t;\n\nprivate:\n\tstd::atomic<ssize_t> m_count;\n\tdetails::Semaphore m_sema;\n\tint m_maxSpins;\n\n\tbool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)\n\t{\n\t\tssize_t oldCount;\n\t\tint spin = m_maxSpins;\n\t\twhile (--spin >= 0)\n\t\t{\n\t\t\toldCount = m_count.load(std::memory_order_relaxed);\n\t\t\tif ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))\n\t\t\t\treturn true;\n\t\t\tstd::atomic_signal_fence(std::memory_order_acquire);\t // Prevent the compiler from collapsing the loop.\n\t\t}\n\t\toldCount = m_count.fetch_sub(1, std::memory_order_acquire);\n\t\tif (oldCount > 0)\n\t\t\treturn true;\n\t\tif (timeout_usecs < 0)\n\t\t{\n\t\t\tif (m_sema.wait())\n\t\t\t\treturn true;\n\t\t}\n\t\tif (timeout_usecs > 0 && m_sema.timed_wait((std::uint64_t)timeout_usecs))\n\t\t\treturn true;\n\t\t// At this point, we've timed out waiting for the semaphore, but the\n\t\t// count is still decremented indicating we may still be waiting on\n\t\t// it. So we have to re-adjust the count, but only if the semaphore\n\t\t// wasn't signaled enough times for us too since then. If it was, we\n\t\t// need to release the semaphore too.\n\t\twhile (true)\n\t\t{\n\t\t\toldCount = m_count.load(std::memory_order_acquire);\n\t\t\tif (oldCount >= 0 && m_sema.try_wait())\n\t\t\t\treturn true;\n\t\t\tif (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tssize_t waitManyWithPartialSpinning(ssize_t max, std::int64_t timeout_usecs = -1)\n\t{\n\t\tassert(max > 0);\n\t\tssize_t oldCount;\n\t\tint spin = m_maxSpins;\n\t\twhile (--spin >= 0)\n\t\t{\n\t\t\toldCount = m_count.load(std::memory_order_relaxed);\n\t\t\tif (oldCount > 0)\n\t\t\t{\n\t\t\t\tssize_t newCount = oldCount > max ? oldCount - max : 0;\n\t\t\t\tif (m_count.compare_exchange_strong(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))\n\t\t\t\t\treturn oldCount - newCount;\n\t\t\t}\n\t\t\tstd::atomic_signal_fence(std::memory_order_acquire);\n\t\t}\n\t\toldCount = m_count.fetch_sub(1, std::memory_order_acquire);\n\t\tif (oldCount <= 0)\n\t\t{\n\t\t\tif ((timeout_usecs == 0) || (timeout_usecs < 0 && !m_sema.wait()) || (timeout_usecs > 0 && !m_sema.timed_wait((std::uint64_t)timeout_usecs)))\n\t\t\t{\n\t\t\t\twhile (true)\n\t\t\t\t{\n\t\t\t\t\toldCount = m_count.load(std::memory_order_acquire);\n\t\t\t\t\tif (oldCount >= 0 && m_sema.try_wait())\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tif (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))\n\t\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (max > 1)\n\t\t\treturn 1 + tryWaitMany(max - 1);\n\t\treturn 1;\n\t}\n\npublic:\n\tLightweightSemaphore(ssize_t initialCount = 0, int maxSpins = 10000) : m_count(initialCount), m_maxSpins(maxSpins)\n\t{\n\t\tassert(initialCount >= 0);\n\t\tassert(maxSpins >= 0);\n\t}\n\n\tbool tryWait()\n\t{\n\t\tssize_t oldCount = m_count.load(std::memory_order_relaxed);\n\t\twhile (oldCount > 0)\n\t\t{\n\t\t\tif (m_count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tbool wait()\n\t{\n\t\treturn tryWait() || waitWithPartialSpinning();\n\t}\n\n\tbool wait(std::int64_t timeout_usecs)\n\t{\n\t\treturn tryWait() || waitWithPartialSpinning(timeout_usecs);\n\t}\n\n\t// Acquires between 0 and (greedily) max, inclusive\n\tssize_t tryWaitMany(ssize_t max)\n\t{\n\t\tassert(max >= 0);\n\t\tssize_t oldCount = m_count.load(std::memory_order_relaxed);\n\t\twhile (oldCount > 0)\n\t\t{\n\t\t\tssize_t newCount = oldCount > max ? oldCount - max : 0;\n\t\t\tif (m_count.compare_exchange_weak(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))\n\t\t\t\treturn oldCount - newCount;\n\t\t}\n\t\treturn 0;\n\t}\n\n\t// Acquires at least one, and (greedily) at most max\n\tssize_t waitMany(ssize_t max, std::int64_t timeout_usecs)\n\t{\n\t\tassert(max >= 0);\n\t\tssize_t result = tryWaitMany(max);\n\t\tif (result == 0 && max > 0)\n\t\t\tresult = waitManyWithPartialSpinning(max, timeout_usecs);\n\t\treturn result;\n\t}\n\t\n\tssize_t waitMany(ssize_t max)\n\t{\n\t\tssize_t result = waitMany(max, -1);\n\t\tassert(result > 0);\n\t\treturn result;\n\t}\n\n\tvoid signal(ssize_t count = 1)\n\t{\n\t\tassert(count >= 0);\n\t\tssize_t oldCount = m_count.fetch_add(count, std::memory_order_release);\n\t\tssize_t toRelease = -oldCount < count ? -oldCount : count;\n\t\tif (toRelease > 0)\n\t\t{\n\t\t\tm_sema.signal((int)toRelease);\n\t\t}\n\t}\n\t\n\tstd::size_t availableApprox() const\n\t{\n\t\tssize_t count = m_count.load(std::memory_order_relaxed);\n\t\treturn count > 0 ? static_cast<std::size_t>(count) : 0;\n\t}\n};\n\n}   // end namespace moodycamel\n"
  },
  {
    "path": "dispenso/thread_id.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/thread_id.h>\n\nnamespace dispenso {\n\nstd::atomic<uint64_t> nextThread{0};\nconstexpr uint64_t kInvalidThread = std::numeric_limits<uint64_t>::max();\nDISPENSO_THREAD_LOCAL uint64_t currentThread = kInvalidThread;\n\nuint64_t threadId() {\n  if (currentThread == kInvalidThread) {\n    currentThread = nextThread.fetch_add(uint64_t{1}, std::memory_order_relaxed);\n  }\n  return currentThread;\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/thread_id.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file thread_id.h\n * @ingroup group_util\n * Utilities for getting a unique thread identifier.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * Get the current thread's identifier, unique within the current process.\n *\n * @return An integer representing the current thread.\n *\n * @note Thread IDs are assumed to not be reused over the lifetime of a process, but this should\n * still enable processes running for thousands of years, even with very poor spawn/kill thread\n * patterns.\n *\n * @note If thread ID is needed for cross-process synchronization, one must fall back on\n * system-specific thread IDs.\n **/\nDISPENSO_DLL_ACCESS uint64_t threadId();\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/thread_pool.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/detail/quanta.h>\n#include <dispenso/thread_pool.h>\n\n#if defined DISPENSO_DEBUG\n#include <iostream>\n#endif // DISPENSO_DEBUG\n\nnamespace dispenso {\n\nnamespace {\nsize_t getAdjustedThreadCount(size_t requested) {\n  static const size_t maxThreads = []() {\n    size_t maxT = std::numeric_limits<size_t>::max();\n\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(push)\n#pragma warning(disable : 4996)\n#endif\n\n    char* envThreads = std::getenv(\"DISPENSO_MAX_THREADS_PER_POOL\");\n\n#if defined(_WIN32) && !defined(__MINGW32__)\n#pragma warning(pop)\n#endif\n\n    if (envThreads) {\n      char* end = nullptr;\n      maxT = std::strtoul(envThreads, &end, 10);\n#if defined DISPENSO_DEBUG\n      std::cout << \"DISPENSO_MAX_THREADS_PER_POOL = \" << maxT << std::endl;\n#endif // DISPENSO_DEBUG\n    }\n    return maxT;\n  }();\n\n  return std::min(requested, maxThreads);\n}\n} // namespace\n\nvoid ThreadPool::PerThreadData::setThread(std::thread&& t) {\n  thread_ = std::move(t);\n}\n\nvoid ThreadPool::PerThreadData::stop() {\n  running_.store(false, std::memory_order_release);\n}\n\nuint32_t ThreadPool::wait(uint32_t currentEpoch) {\n  if (sleepLengthUs_ > 0) {\n    return epochWaiter_.waitFor(currentEpoch, sleepLengthUs_.load(std::memory_order_acquire));\n  } else {\n    return epochWaiter_.current();\n  }\n}\nvoid ThreadPool::wake() {\n  epochWaiter_.bumpAndWake();\n}\n\ninline bool ThreadPool::PerThreadData::running() {\n  return running_.load(std::memory_order_acquire);\n}\n\nThreadPool::ThreadPool(size_t n, size_t poolLoadMultiplier)\n    : poolLoadMultiplier_(poolLoadMultiplier),\n      poolLoadFactor_(static_cast<ssize_t>(getAdjustedThreadCount(n) * poolLoadMultiplier)),\n      numThreads_(static_cast<ssize_t>(getAdjustedThreadCount(n))) {\n  detail::registerFineSchedulerQuanta();\n#if defined DISPENSO_DEBUG\n  assert(poolLoadMultiplier > 0);\n#endif // DISPENSO_DEBUG\n  for (size_t i = 0; i < static_cast<size_t>(numThreads_); ++i) {\n    threads_.emplace_back();\n    threads_.back().setThread(std::thread([this, &back = threads_.back()]() { threadLoop(back); }));\n  }\n}\n\nThreadPool::PerThreadData::~PerThreadData() {}\n\nvoid ThreadPool::threadLoop(PerThreadData& data) {\n  // On Windows, wake syscalls (WakeByAddressSingle) are expensive per-thread\n  // kernel transitions, so spin longer before sleeping to avoid costly\n  // sleep/wake cycles.\n#if defined(_WIN32)\n  static constexpr int kBackoffYield = 100;\n  static constexpr int kBackoffSleep = kBackoffYield + 20;\n#else\n  static constexpr int kBackoffYield = 50;\n  static constexpr int kBackoffSleep = kBackoffYield + 5;\n#endif\n\n  moodycamel::ConsumerToken ctoken(work_);\n  moodycamel::ProducerToken ptoken(work_);\n\n  OnceFunction next;\n\n  int failCount = 0;\n  detail::PerPoolPerThreadInfo::registerPool(this, &ptoken);\n  uint32_t epoch = epochWaiter_.current();\n\n  if (enableEpochWaiter_) {\n    while (data.running()) {\n      int localWorkDone = 0;\n      while (true) {\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n        bool got = work_.try_dequeue(ctoken, next);\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n        if (!got) {\n          break;\n        }\n        OnceFunction task(std::move(next));\n        task();\n        ++localWorkDone;\n        if (localWorkDone >= kWorkBatchSize) {\n          workRemaining_.fetch_sub(localWorkDone, std::memory_order_relaxed);\n          localWorkDone = 0;\n        }\n        failCount = 0;\n      }\n      if (localWorkDone > 0) {\n        workRemaining_.fetch_sub(localWorkDone, std::memory_order_relaxed);\n      }\n\n      ++failCount;\n\n      detail::cpuRelax();\n      if (failCount > kBackoffSleep) {\n        numSleeping_.fetch_add(1, std::memory_order_acq_rel);\n        epoch = wait(epoch);\n        numSleeping_.fetch_sub(1, std::memory_order_acq_rel);\n        failCount = 0;\n      } else if (failCount > kBackoffYield) {\n        std::this_thread::yield();\n      }\n    }\n  } else {\n    while (data.running()) {\n      while (true) {\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n        bool got = work_.try_dequeue(ctoken, next);\n        DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n        if (!got) {\n          break;\n        }\n        executeNext(std::move(next));\n        failCount = 0;\n      }\n\n      ++failCount;\n\n      detail::cpuRelax();\n      if (failCount > kBackoffSleep) {\n        epoch = wait(epoch);\n      } else if (failCount > kBackoffYield) {\n        std::this_thread::yield();\n      }\n    }\n  }\n}\n\nvoid ThreadPool::resizeLocked(ssize_t sn) {\n  sn = getAdjustedThreadCount(sn);\n\n  assert(sn >= 0);\n  size_t n = static_cast<size_t>(sn);\n\n  if (n < threads_.size()) {\n    for (size_t i = n; i < threads_.size(); ++i) {\n      threads_[i].stop();\n    }\n\n    while (threads_.size() > n) {\n      wake();\n      threads_.back().thread_.join();\n      threads_.pop_back();\n    }\n\n  } else if (n > threads_.size()) {\n    for (size_t i = threads_.size(); i < n; ++i) {\n      threads_.emplace_back();\n      threads_.back().setThread(\n          std::thread([this, &back = threads_.back()]() { threadLoop(back); }));\n    }\n  }\n  poolLoadFactor_.store(static_cast<ssize_t>(n * poolLoadMultiplier_), std::memory_order_relaxed);\n  numThreads_.store(sn, std::memory_order_relaxed);\n\n  if (!sn) {\n    // Pool will run future tasks inline since we have no threads, but we still need to empty\n    // current set of tasks\n    while (tryExecuteNext()) {\n    }\n  }\n}\n\nThreadPool::~ThreadPool() {\n#if defined DISPENSO_DEBUG\n  assert(outstandingTaskSets_.load(std::memory_order_acquire) == 0);\n#endif // DISPENSO_DEBUG\n\n  // Strictly speaking, it is unnecessary to lock this in the destructor; however, it could be a\n  // useful diagnostic to learn that the mutex is already locked when we reach this point.\n  std::unique_lock<std::mutex> lk(threadsMutex_, std::try_to_lock);\n  assert(lk.owns_lock());\n\n  // Mark all threads as stopped first, then wake them all at once. The previous\n  // approach (stop + wake one at a time) was fragile: a wake() could reach an\n  // already-awake thread while another thread remained sleeping, forcing it to\n  // wait for the epoch timeout (e.g. 30ms) to notice the stop flag. Under TSAN\n  // this caused severe slowdowns in ThreadPool destruction.\n  for (auto& t : threads_) {\n    t.stop();\n  }\n  ssize_t numThreads = static_cast<ssize_t>(threads_.size());\n  if (numThreads > 0) {\n    wakeN(numThreads);\n  }\n\n  while (tryExecuteNext()) {\n  }\n\n  for (auto& t : threads_) {\n    t.thread_.join();\n  }\n  threads_.clear();\n\n  while (tryExecuteNext()) {\n  }\n}\nThreadPool& globalThreadPool() {\n  // It should be illegal to access globalThreadPool after exiting main.\n  // We default to hardware threads minus one because the calling thread usually is involved in\n  // computation.\n  static ThreadPool pool(std::thread::hardware_concurrency() - 1);\n  return pool;\n}\n\nvoid resizeGlobalThreadPool(size_t numThreads) {\n  globalThreadPool().resize(static_cast<ssize_t>(numThreads));\n}\n\nvoid ThreadPool::wakeN(ssize_t n) {\n#if defined(_WIN32)\n  // On Windows, always use WakeAll. WakeByAddressSingle has no batch wake\n  // count, so multiple calls means O(N) kernel transitions. A single WakeAll\n  // is one transition and keeps threads in their spin phase (kBackoffYield\n  // iterations) where they can absorb follow-up work without re-waking.\n  (void)n;\n  epochWaiter_.bumpAndWakeAll();\n#else\n  ssize_t sleeping = numSleeping_.load(std::memory_order_relaxed);\n  constexpr unsigned kWakeAllMultiplier = 2;\n  if (static_cast<unsigned>(n) * kWakeAllMultiplier >= static_cast<unsigned>(sleeping)) {\n    epochWaiter_.bumpAndWakeAll();\n  } else {\n    epochWaiter_.bumpAndWakeN(static_cast<int>(n), static_cast<int>(sleeping));\n  }\n#endif\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/thread_pool.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file thread_pool.h\n * @ingroup group_core\n * A file providing ThreadPool.  This is the heart of dispenso.  All other scheduling paradigms,\n * including TaskSets, Futures, pipelines, and parallel loops, are built on top of ThreadPool.\n **/\n\n#pragma once\n\n#include <atomic>\n#include <cassert>\n#include <condition_variable>\n#include <cstdlib>\n#include <deque>\n#include <iterator>\n#include <mutex>\n#include <thread>\n\n#include <moodycamel/concurrentqueue.h>\n\n#include <dispenso/detail/epoch_waiter.h>\n#include <dispenso/detail/per_thread_info.h>\n#include <dispenso/once_function.h>\n#include <dispenso/platform.h>\n#include <dispenso/tsan_annotations.h>\n\nnamespace dispenso {\n\n#if !defined(DISPENSO_WAKEUP_ENABLE)\n#if defined(_WIN32) || defined(__linux__) || defined(__MACH__)\n#define DISPENSO_WAKEUP_ENABLE 1\n#else\n#define DISPENSO_WAKEUP_ENABLE 0\n#endif // platform\n#endif // DISPENSO_WAKEUP_ENABLE\n\n#if !defined(DISPENSO_POLL_PERIOD_US)\n#if defined(_WIN32)\n#define DISPENSO_POLL_PERIOD_US 1000\n#else\n#if !(DISPENSO_WAKEUP_ENABLE)\n#define DISPENSO_POLL_PERIOD_US 200\n#else\n#define DISPENSO_POLL_PERIOD_US (1 << 15) // Determined empirically good on dual Xeon Linux\n#endif // DISPENSO_WAKEUP_ENABLE\n#endif // PLATFORM\n#endif // DISPENSO_POLL_PERIOD_US\n\nconstexpr uint32_t kDefaultSleepLenUs = DISPENSO_POLL_PERIOD_US;\n\nconstexpr bool kDefaultWakeupEnable = DISPENSO_WAKEUP_ENABLE;\n\n/**\n * A simple tag specifier that can be fed to TaskSets and\n * ThreadPools to denote that the current thread should never immediately execute a functor, but\n * rather, the functor should always be placed in the ThreadPool's queue.\n **/\nstruct ForceQueuingTag {};\n\n/**\n * The basic executor for dispenso.  It provides typical thread pool functionality, plus allows work\n * stealing by related types (e.g. TaskSet, Future, etc...), which prevents deadlock when waiting\n * for pool-recursive tasks.\n */\nclass alignas(kCacheLineSize) ThreadPool {\n public:\n  /**\n   * Construct a thread pool.\n   *\n   * @param n The number of threads to spawn at construction.\n   * @param poolLoadMultiplier A parameter that specifies how overloaded the pool should be before\n   * allowing the current thread to self-steal work.\n   **/\n  DISPENSO_DLL_ACCESS ThreadPool(size_t n, size_t poolLoadMultiplier = 32);\n\n  /**\n   * Enable or disable signaling wake functionality.  If enabled, this will try to ensure that\n   * threads are woken up proactively when work has not been available and it becomes available.\n   * This function is blocking and potentially very slow.  Repeated use is discouraged.\n   *\n   * @param enable If set true, turns on signaling wake.  If false, turns it off.\n   * @param sleepDuration If enable is true, this is the length of time a thread will wait for a\n   * signal before waking up.  If enable is false, this is the length of time a thread will sleep\n   * between polling.\n   *\n   * @note It is highly recommended to leave signaling wake enabled on Windows platforms, as\n   * sleeping/polling tends to perform poorly for intermittent workloads.  For Mac/Linux platforms,\n   * it is okay to enable signaling wake, particularly if you wish to set a longer expected duration\n   * between work.  If signaling wake is disabled, ensure sleepDuration is small (e.g. 200us) for\n   * best performance.  Most users will not need to call this function, as defaults are reasonable.\n   *\n   *\n   **/\n  template <class Rep, class Period>\n  void setSignalingWake(\n      bool enable,\n      const std::chrono::duration<Rep, Period>& sleepDuration =\n          std::chrono::microseconds(kDefaultSleepLenUs)) {\n    setSignalingWake(\n        enable,\n        static_cast<uint32_t>(\n            std::chrono::duration_cast<std::chrono::microseconds>(sleepDuration).count()));\n  }\n\n  /**\n   * Change the number of threads backing the thread pool.  This is a blocking and potentially\n   * slow operation, and repeatedly resizing is discouraged.\n   *\n   * @param n The number of threads in use after call completion\n   **/\n  DISPENSO_DLL_ACCESS void resize(ssize_t n) {\n    std::lock_guard<std::mutex> lk(threadsMutex_);\n    resizeLocked(n);\n  }\n\n  /**\n   * Get the number of threads backing the pool.  If called concurrently to <code>resize</code>, the\n   * number returned may be stale.\n   *\n   * @return The current number of threads backing the pool.\n   **/\n  ssize_t numThreads() const {\n    return numThreads_.load(std::memory_order_relaxed);\n  }\n\n  /**\n   * Schedule a functor to be executed.  If the pool's load factor is high, execution may happen\n   * inline by the calling thread.\n   *\n   * @param f The functor to be executed.  <code>f</code>'s signature must match void().  Best\n   * performance will come from passing lambdas, other concrete functors, or OnceFunction, but\n   * std::function or similarly type-erased objects will also work.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f);\n\n  /**\n   * Schedule a functor to be executed.  The functor will always be queued and executed by pool\n   * threads.\n   *\n   * @param f The functor to be executed.  <code>f</code>'s signature must match void().  Best\n   * performance will come from passing lambdas, other concrete functors, or OnceFunction, but\n   * std::function or similarly type-erased objects will also work.\n   **/\n  template <typename F>\n  DISPENSO_REQUIRES(OnceCallableFunc<F>)\n  void schedule(F&& f, ForceQueuingTag);\n\n  /**\n   * Schedule multiple functors to be executed in bulk.  This is more efficient than calling\n   * schedule() multiple times when you have many tasks to submit, as it reduces atomic contention\n   * and allows for better thread wakeup behavior.\n   *\n   * @param count The number of functors to schedule.\n   * @param gen A generator functor that takes an index and returns a functor to execute.\n   *            gen(i) will be called for i in [0, count) to produce each task.\n   *\n   * @note Work is enqueued in chunks and interleaved with inline execution based on the pool's\n   *       load factor, preventing both pool thread starvation and excessive queueing overhead.\n   **/\n  template <typename Generator>\n  void scheduleBulk(size_t count, Generator&& gen);\n\n  /**\n   * Destruct the pool.  This destructor is blocking until all queued work is completed.  It is\n   * illegal to call the destructor while any other thread makes calls to the pool (as is generally\n   * the case with C++ classes).\n   **/\n  DISPENSO_DLL_ACCESS ~ThreadPool();\n\n private:\n  class PerThreadData {\n   public:\n    void setThread(std::thread&& t);\n\n    bool running();\n\n    void stop();\n\n    ~PerThreadData();\n\n   public:\n    alignas(kCacheLineSize) std::thread thread_;\n    std::atomic<bool> running_{true};\n  };\n\n  DISPENSO_DLL_ACCESS uint32_t wait(uint32_t priorEpoch);\n  DISPENSO_DLL_ACCESS void wake();\n  DISPENSO_DLL_ACCESS void wakeN(ssize_t n);\n\n  void setSignalingWake(bool enable, uint32_t sleepDurationUs) {\n    std::lock_guard<std::mutex> lk(threadsMutex_);\n    ssize_t currentPoolSize = numThreads();\n    resizeLocked(0);\n    enableEpochWaiter_.store(enable, std::memory_order_release);\n    sleepLengthUs_.store(sleepDurationUs, std::memory_order_release);\n    resizeLocked(currentPoolSize);\n  }\n\n  DISPENSO_DLL_ACCESS void resizeLocked(ssize_t n);\n\n  void executeNext(OnceFunction work);\n\n  DISPENSO_DLL_ACCESS void threadLoop(PerThreadData& threadData);\n\n  bool tryExecuteNext();\n  bool tryExecuteNextFromProducerToken(moodycamel::ProducerToken& token);\n\n  template <typename F>\n  void schedule(moodycamel::ProducerToken& token, F&& f);\n\n  template <typename F>\n  void schedule(moodycamel::ProducerToken& token, F&& f, ForceQueuingTag);\n\n  // Core bulk enqueue: unconditionally stage, enqueue, and wake for a chunk of tasks.\n  // Caller is responsible for load factor checks. Count should be small (e.g. <= 2*numThreads).\n  // When a producer token is provided, uses token-based enqueue for better throughput.\n  template <typename Generator>\n  void\n  scheduleBulkEnqueue(size_t count, Generator&& gen, moodycamel::ProducerToken* token = nullptr);\n\n  // The non-atomic read of two separate atomics (numSleeping_ and workRemaining_) can\n  // race, potentially causing a missed wake in rare cases. This is benign: the epoch\n  // waiter's sleep timeout (sleepLengthUs_) provides a safety net, so a missed wake only\n  // delays wakeup by up to that duration, never causes a hang. Subsequent schedule()\n  // calls will trigger wakes.\n  void conditionallyWake() {\n    if (enableEpochWaiter_.load(std::memory_order_acquire)) {\n      ssize_t sleeping = numSleeping_.load(std::memory_order_acquire);\n      if (sleeping > 0) {\n        // Only wake if there's more pending work than awake threads can handle.\n        // Don't count the caller — it may be a pool thread that will continue\n        // dequeuing its own work, not processing what it just submitted.\n        ssize_t awake = numThreads_.load(std::memory_order_relaxed) - sleeping;\n        ssize_t pending = workRemaining_.load(std::memory_order_relaxed);\n        if (pending > awake) {\n          wake();\n        }\n      }\n    }\n  }\n\n public:\n  // If we are not yet C++17, we provide aligned new/delete to avoid false sharing.\n#if __cplusplus < 201703L\n  static void* operator new(size_t sz) {\n    return detail::alignedMalloc(sz);\n  }\n  static void operator delete(void* ptr) {\n    return detail::alignedFree(ptr);\n  }\n#endif // __cplusplus\n\n private:\n  // Number of tasks each thread accumulates before flushing workRemaining_.\n  // This batching reduces atomic contention in threadLoop, but inflates\n  // workRemaining_ by up to kWorkBatchSize * numThreads, so poolLoadFactor_\n  // must be reduced accordingly for accurate load-shedding in schedule().\n  static constexpr int kWorkBatchSize = 8;\n\n  mutable std::mutex threadsMutex_;\n  std::deque<PerThreadData> threads_;\n  size_t poolLoadMultiplier_;\n\n  // These atomics are read frequently in the hot schedule() path, so they need\n  // cache-line alignment to avoid false sharing with the mutex/deque above.\n  alignas(kCacheLineSize) std::atomic<ssize_t> poolLoadFactor_;\n  std::atomic<ssize_t> numThreads_;\n\n  moodycamel::ConcurrentQueue<OnceFunction> work_;\n\n  alignas(kCacheLineSize) std::atomic<ssize_t> numSleeping_{0};\n\n  alignas(kCacheLineSize) std::atomic<ssize_t> workRemaining_{0};\n\n  alignas(kCacheLineSize) detail::EpochWaiter epochWaiter_;\n  alignas(kCacheLineSize) std::atomic<bool> enableEpochWaiter_{kDefaultWakeupEnable};\n  std::atomic<uint32_t> sleepLengthUs_{kDefaultSleepLenUs};\n\n#if defined DISPENSO_DEBUG\n  alignas(kCacheLineSize) std::atomic<ssize_t> outstandingTaskSets_{0};\n#endif // NDEBUG\n\n  friend class ConcurrentTaskSet;\n  friend class TaskSet;\n  friend class TaskSetBase;\n};\n\n/**\n * Get access to the global thread pool.\n *\n * @return the global thread pool\n **/\nDISPENSO_DLL_ACCESS ThreadPool& globalThreadPool();\n\n/**\n * Change the number of threads backing the global thread pool.\n *\n * @param numThreads The number of threads to back the global thread pool.\n **/\nDISPENSO_DLL_ACCESS void resizeGlobalThreadPool(size_t numThreads);\n\n// ----------------------------- Implementation details -------------------------------------\n\ntemplate <typename F>\nDISPENSO_REQUIRES(OnceCallableFunc<F>)\ninline void ThreadPool::schedule(F&& f) {\n  ssize_t curWork = workRemaining_.load(std::memory_order_relaxed);\n  ssize_t quickLoadFactor = numThreads_.load(std::memory_order_relaxed);\n  quickLoadFactor += quickLoadFactor / 2;\n  if ((detail::PerPoolPerThreadInfo::isPoolRecursive(this) && curWork > quickLoadFactor) ||\n      (curWork > poolLoadFactor_.load(std::memory_order_relaxed))) {\n    f();\n  } else {\n    schedule(std::forward<F>(f), ForceQueuingTag());\n  }\n}\n\ntemplate <typename F>\nDISPENSO_REQUIRES(OnceCallableFunc<F>)\ninline void ThreadPool::schedule(F&& f, ForceQueuingTag) {\n  if (auto* token =\n          static_cast<moodycamel::ProducerToken*>(detail::PerPoolPerThreadInfo::producer(this))) {\n    schedule(*token, std::forward<F>(f), ForceQueuingTag());\n    return;\n  }\n\n  if (!numThreads_.load(std::memory_order_relaxed)) {\n    f();\n    return;\n  }\n  workRemaining_.fetch_add(1, std::memory_order_release);\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n  bool enqueued = work_.enqueue({std::forward<F>(f)});\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n  (void)(enqueued); // unused\n  assert(enqueued);\n\n  conditionallyWake();\n}\n\ntemplate <typename F>\ninline void ThreadPool::schedule(moodycamel::ProducerToken& token, F&& f) {\n  ssize_t curWork = workRemaining_.load(std::memory_order_relaxed);\n  ssize_t quickLoadFactor = numThreads_.load(std::memory_order_relaxed);\n  quickLoadFactor += quickLoadFactor / 2;\n  if ((detail::PerPoolPerThreadInfo::isPoolRecursive(this) && curWork > quickLoadFactor) ||\n      (curWork > poolLoadFactor_.load(std::memory_order_relaxed))) {\n    f();\n  } else {\n    schedule(token, std::forward<F>(f), ForceQueuingTag());\n  }\n}\n\ntemplate <typename F>\ninline void ThreadPool::schedule(moodycamel::ProducerToken& token, F&& f, ForceQueuingTag) {\n  if (!numThreads_.load(std::memory_order_relaxed)) {\n    f();\n    return;\n  }\n  workRemaining_.fetch_add(1, std::memory_order_release);\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n  bool enqueued = work_.enqueue(token, {std::forward<F>(f)});\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n  (void)(enqueued); // unused\n  assert(enqueued);\n\n  conditionallyWake();\n}\n\ninline bool ThreadPool::tryExecuteNext() {\n  OnceFunction next;\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n  bool dequeued = work_.try_dequeue(next);\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n  if (dequeued) {\n    executeNext(std::move(next));\n    return true;\n  }\n  return false;\n}\n\ninline bool ThreadPool::tryExecuteNextFromProducerToken(moodycamel::ProducerToken& token) {\n  OnceFunction next;\n  if (work_.try_dequeue_from_producer(token, next)) {\n    executeNext(std::move(next));\n    return true;\n  }\n  return false;\n}\n\ninline void ThreadPool::executeNext(OnceFunction next) {\n  next();\n  workRemaining_.fetch_add(-1, std::memory_order_relaxed);\n}\n\nnamespace detail {\n// Generating iterator for scheduleBulkEnqueue. Produces OnceFunction objects\n// on-the-fly during enqueue_bulk, avoiding the need for a staging buffer.\n// moodycamel's enqueue_bulk uses single-pass input iterator semantics.\ntemplate <typename Generator>\nstruct BulkGenIter {\n  using difference_type = std::ptrdiff_t;\n  using value_type = OnceFunction;\n  using pointer = OnceFunction*;\n  using reference = OnceFunction&;\n  using iterator_category = std::input_iterator_tag;\n\n  Generator* gen;\n  size_t index;\n  OnceFunction operator*() {\n    return (*gen)(index);\n  }\n  BulkGenIter& operator++() {\n    ++index;\n    return *this;\n  }\n  BulkGenIter operator++(int) {\n    BulkGenIter tmp = *this;\n    ++index;\n    return tmp;\n  }\n};\n} // namespace detail\n\ntemplate <typename Generator>\nvoid ThreadPool::scheduleBulkEnqueue(\n    size_t count,\n    Generator&& gen,\n    moodycamel::ProducerToken* token) {\n  detail::BulkGenIter<typename std::remove_reference<Generator>::type> it{&gen, 0};\n\n  // Single atomic update + bulk enqueue\n  workRemaining_.fetch_add(static_cast<ssize_t>(count), std::memory_order_release);\n\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();\n  bool enqueued;\n  if (token) {\n    enqueued = work_.enqueue_bulk(*token, it, count);\n  } else {\n    enqueued = work_.enqueue_bulk(it, count);\n  }\n  DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END();\n  (void)(enqueued);\n  assert(enqueued);\n\n  // Wake appropriate threads\n  if (enableEpochWaiter_.load(std::memory_order_acquire)) {\n    ssize_t sleeping = numSleeping_.load(std::memory_order_acquire);\n    ssize_t toWake = std::min(sleeping, static_cast<ssize_t>(count));\n    if (toWake > 0) {\n      wakeN(toWake);\n    }\n  }\n}\n\ntemplate <typename Generator>\nvoid ThreadPool::scheduleBulk(size_t count, Generator&& gen) {\n  if (count == 0) {\n    return;\n  }\n\n  ssize_t numPool = numThreads_.load(std::memory_order_relaxed);\n  if (!numPool) {\n    // No threads in pool - execute all inline\n    for (size_t i = 0; i < count; ++i) {\n      gen(i)();\n    }\n    return;\n  }\n\n  // Process in chunks, interleaving enqueue and inline execution based on load.\n  size_t chunkSize = static_cast<size_t>(numPool) + static_cast<size_t>(numPool) / 2;\n  if (chunkSize < 1) {\n    chunkSize = 1;\n  }\n  size_t i = 0;\n  while (i < count) {\n    ssize_t curWork = workRemaining_.load(std::memory_order_relaxed);\n    ssize_t loadFactor = poolLoadFactor_.load(std::memory_order_relaxed);\n    if (curWork > loadFactor) {\n      // Over load factor - execute one task inline, then re-check\n      gen(i)();\n      ++i;\n    } else {\n      // Under load factor - enqueue a chunk\n      ssize_t room = loadFactor - curWork;\n      size_t toEnqueue = std::min({count - i, chunkSize, static_cast<size_t>(room)});\n      if (toEnqueue == 0) {\n        toEnqueue = 1;\n      }\n      size_t base = i;\n      scheduleBulkEnqueue(toEnqueue, [&gen, base](size_t j) { return gen(base + j); });\n      i += toEnqueue;\n    }\n  }\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/timed_task.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <iostream>\n\n#include <dispenso/detail/quanta.h>\n#include <dispenso/timed_task.h>\n\nnamespace dispenso {\n\nTimedTaskScheduler::TimedTaskScheduler(ThreadPriority prio) : priority_(prio) {\n  thread_ = std::thread([this, prio]() {\n    detail::registerFineSchedulerQuanta();\n    if (!setCurrentThreadPriority(prio)) {\n      std::cerr << \"Couldn't set thread priority\" << std::endl;\n    }\n    timeQueueRunLoop();\n  });\n}\nTimedTaskScheduler::~TimedTaskScheduler() {\n  {\n    std::lock_guard<std::mutex> lk(queueMutex_);\n    running_ = false;\n  }\n  epoch_.bumpAndWake();\n  thread_.join();\n}\n\nvoid TimedTaskScheduler::kickOffTask(std::shared_ptr<detail::TimedTaskImpl> next, double curTime) {\n  size_t remaining = next->timesToRun.fetch_sub(1, std::memory_order_acq_rel);\n  if (remaining == 1) {\n    auto* np = next.get();\n    np->func(std::move(next));\n  } else if (remaining > 1) {\n    next->func(next);\n\n    if (next->steady) {\n      next->nextAbsTime += next->period;\n    } else {\n      next->nextAbsTime = curTime + next->period;\n    }\n    std::lock_guard<std::mutex> lk(queueMutex_);\n    tasks_.push(std::move(next));\n  }\n}\n\nconstexpr double kSmallTimeBuffer = 10e-6;\n\nvoid TimedTaskScheduler::timeQueueRunLoop() {\n#if defined(_WIN32)\n  constexpr double kSpinYieldBuffer = 1e-3;\n  constexpr double kSpinBuffer = 100e-6;\n#else\n  constexpr double kSpinYieldBuffer = 500e-6;\n  constexpr double kSpinBuffer = 50e-6;\n#endif // platform\n  constexpr double kConvertToUs = 1e6;\n\n  uint32_t curEpoch = epoch_.current();\n\n  while (true) {\n    {\n      std::unique_lock<std::mutex> lk(queueMutex_);\n      if (priority_ != getCurrentThreadPriority()) {\n        setCurrentThreadPriority(priority_);\n      }\n\n      if (!running_) {\n        break;\n      }\n      if (tasks_.empty()) {\n        lk.unlock();\n        curEpoch = epoch_.wait(curEpoch);\n        continue;\n      }\n    }\n    double curTime = getTime();\n    double timeRemaining;\n    std::unique_lock<std::mutex> lk(queueMutex_);\n    timeRemaining = tasks_.top()->nextAbsTime - curTime;\n    if (timeRemaining < kSmallTimeBuffer) {\n      auto next = tasks_.top();\n      tasks_.pop();\n      lk.unlock();\n\n      kickOffTask(std::move(next), curTime);\n    } else if (timeRemaining < kSpinBuffer) {\n      continue;\n    } else if (timeRemaining < kSpinYieldBuffer) {\n      lk.unlock();\n      std::this_thread::yield();\n      continue;\n    } else {\n      lk.unlock();\n      curEpoch = epoch_.waitFor(\n          curEpoch, static_cast<uint64_t>((timeRemaining - kSpinBuffer) * kConvertToUs));\n    }\n  }\n}\n\nvoid TimedTaskScheduler::addTimedTask(std::shared_ptr<detail::TimedTaskImpl> task) {\n  double curTime = getTime();\n  double timeRemaining;\n  timeRemaining = task->nextAbsTime - curTime;\n  if (timeRemaining < kSmallTimeBuffer) {\n    kickOffTask(std::move(task), curTime);\n  } else {\n    std::lock_guard<std::mutex> lk(queueMutex_);\n    tasks_.push(std::move(task));\n  }\n  epoch_.bumpAndWake();\n}\n\nTimedTaskScheduler& globalTimedTaskScheduler() {\n  static TimedTaskScheduler scheduler;\n  return scheduler;\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/timed_task.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file timed_task.h\n * @ingroup group_async\n * Utilities for delaying a task until a future time and periodic scheduling.\n **/\n\n#pragma once\n\n#include <chrono>\n#include <functional>\n#include <memory>\n#include <queue>\n\n#include <dispenso/detail/timed_task_impl.h>\n#include <dispenso/priority.h>\n#include <dispenso/timing.h>\n\nnamespace dispenso {\n\n/**\n * For periodic tasks, this type will describe the behavior of how tasks are scheduled\n **/\nenum class TimedTaskType {\n  kNormal ///< Schedule the next task at period plus the time the first or most recent task ran\n  ,\n  kSteady ///< Schedule the next task at period plus the time the first or most recent task was\n          ///< scheduled for\n};\n\n/**\n * A timed task type.  This encapsulates a function that will run at a time scheduled in the future,\n * and optionally periodically for a specified number of times.\n **/\n\nclass TimedTask {\n public:\n  TimedTask(const TimedTask&) = delete;\n  /** Move constructor. */\n  TimedTask(TimedTask&& other) : impl_(std::move(other.impl_)) {}\n\n  TimedTask& operator=(const TimedTask&) = delete;\n  TimedTask& operator=(TimedTask&& other) {\n    impl_ = std::move(other.impl_);\n    return *this;\n  }\n\n  /**\n   * Cancel the task.  No further runs to the underlying function will occur (though any calls in\n   * progress will complete).\n   **/\n  void cancel() {\n    impl_->timesToRun.store(0, std::memory_order_release);\n    impl_->flags.fetch_or(detail::kFFlagsCancelled, std::memory_order_release);\n  }\n\n  /**\n   * Detach this task so that it cannot block in destruction, and destruction does not cancel\n   * further runs to the underlying function.  This is only to be used in cases where the underlying\n   * schedulable and any function resources are expected to outlive any other copy of the task.\n   **/\n  void detach() {\n    impl_->flags.fetch_or(detail::kFFlagsDetached, std::memory_order_release);\n  }\n\n  /**\n   * See how many calls there have been to the underlying function have completed thus far.\n   *\n   * @return the count of calls made this far to the underlying function.\n   **/\n  size_t calls() const {\n    return impl_->count.load(std::memory_order_acquire);\n  }\n\n  /**\n   * Destroy the timed task.  If detach() has not been called, this will cancel further calls to the\n   * underlying scheduled function, and will wait if necessary until the function is no longer in\n   * progress.  This is to naturally protect resources that may be used by the function.  If\n   * detach() was called, the destructor will not block.\n   *\n   **/\n  ~TimedTask() {\n    if (!impl_ || impl_->flags.load(std::memory_order_acquire) & detail::kFFlagsDetached) {\n      return;\n    }\n    cancel();\n    while (impl_->inProgress.load(std::memory_order_acquire)) {\n    }\n    // Now we can safely destroy the underlying function.  We do this here because we can't risk\n    // that func may call code in it's destructor that may no longer be relevant after this\n    // TimedTask destructor completes.\n    impl_->func = {};\n  }\n\n private:\n  template <typename Schedulable, typename F>\n  TimedTask(\n      Schedulable& sched,\n      F&& f,\n      double nextRunAbs,\n      double period = 0.0,\n      size_t timesToRun = 1,\n      TimedTaskType type = TimedTaskType::kNormal)\n      : impl_(\n            detail::make_shared<detail::TimedTaskImpl>(\n                timesToRun,\n                nextRunAbs,\n                period,\n                std::forward<F>(f),\n                sched,\n                type == TimedTaskType::kSteady)) {}\n\n  std::shared_ptr<detail::TimedTaskImpl> impl_;\n\n  friend class TimedTaskScheduler;\n}; // namespace dispenso\n\n/**\n * A timed-task scheduler running on a single thread. This allows multiple schedulers if necessary,\n * if e.g. you wish to schedule against InlineInvoker backing schedulable and you're running\n * a lot of relatively quick timed tasks.Most people should just use the global timed task\n * scheduler.\n **/\nclass TimedTaskScheduler {\n public:\n  /**\n   * Create a TimedTaskScheduler with specified priority\n   *\n   * @param priority The priority to set.  For highest level of periodicity accuracy, use kRealtime.\n   * @note Priorities above kNormal should be used sparingly, and only short-running tasks should be\n   * run inline to avoid bad OS responsivity.  When using a ThreadPool Schedulable, tasks can be\n   * long running.\n   **/\n  DISPENSO_DLL_ACCESS explicit TimedTaskScheduler(\n      ThreadPriority priority = ThreadPriority::kNormal);\n  DISPENSO_DLL_ACCESS ~TimedTaskScheduler();\n\n  /**\n   * Set the priority for the backing thread.  See note for constructor.\n   **/\n  void setPriority(ThreadPriority priority) {\n    std::lock_guard<std::mutex> lk(queueMutex_);\n    priority_ = priority;\n  }\n\n  /**\n   * Schedule a task\n   *\n   * @param sched A backing schedulable, such as ImmediateInvoker, NewThreadInvoker, TaskSet, or\n   *        ThreadPool to run the function in when it is scheduled.\n   * @param func A bool() function to run when scheduled.  The function may return true to indicate\n   *        it should continue to be scheduled, or false to cancel.\n   * @param nextRunAbs The absolute time to run the function.  Time scale is expected to match\n   *        getTime() for absolute times.\n   * @param period The period in seconds.\n   * @param timesToRun The number of times to run the function.  After that number, the function\n   *        will not be called again.\n   * @param type The type of periodicity (if any).\n   **/\n  template <typename Schedulable, typename F>\n  TimedTask schedule(\n      Schedulable& sched,\n      F&& func,\n      double nextRunAbs,\n      double period = 0.0,\n      size_t timesToRun = 1,\n      TimedTaskType type = TimedTaskType::kNormal) {\n    TimedTask task(sched, std::forward<F>(func), nextRunAbs, period, timesToRun, type);\n    addTimedTask(task.impl_);\n    return task;\n  }\n\n  /**\n   * Schedule a task to run once at a time in the future\n   *\n   * @param sched A backing schedulable, such as ImmediateInvoker, NewThreadInvoker, TaskSet, or\n   *        ThreadPool to run the function in when it is scheduled.\n   * @param func A bool() function to run when scheduled.  The function may return true to indicate\n   *        it should continue to be scheduled, or false to cancel.\n   * @param timeInFuture the amount of time from current at which to schedule the function\n   **/\n  template <typename Schedulable, typename Rep, typename Period, typename F>\n  TimedTask\n  schedule(Schedulable& sched, F&& func, const std::chrono::duration<Rep, Period>& timeInFuture) {\n    return schedule(sched, std::forward<F>(func), toNextRun(timeInFuture));\n  }\n\n  /**\n   * Schedule a task to run once at a time in the future\n   *\n   * @param sched A backing schedulable, such as ImmediateInvoker, NewThreadInvoker, TaskSet, or\n   *        ThreadPool to run the function in when it is scheduled.\n   * @param func A bool() function to run when scheduled.  The function may return true to indicate\n   *        it should continue to be scheduled, or false to cancel.\n   * @param nextRunTime An absolute time to run the function.  If in the past, func will run\n   *        immediately.\n   **/\n  template <typename Schedulable, typename Clock, typename Duration, typename F>\n  TimedTask schedule(\n      Schedulable& sched,\n      F&& func,\n      const std::chrono::time_point<Clock, Duration>& nextRunTime) {\n    return schedule(sched, std::forward<F>(func), toNextRun(nextRunTime));\n  }\n\n  /**\n   * Schedule a task to run periodically\n   *\n   * @param sched A backing schedulable, such as ImmediateInvoker, NewThreadInvoker, TaskSet, or\n   *        ThreadPool to run the function in when it is scheduled.\n   * @param func A bool() function to run when scheduled.  The function may return true to indicate\n   *        it should continue to be scheduled, or false to cancel.\n   * @param timeInFuture the amount of time from current at which to schedule the function\n   * @param period The period defining the run frequency\n   * @param timesToRun The number of times to run the function.  After that number, the function\n   *        will not be called again.\n   * @param type The type of periodicity (if any).\n   **/\n  template <typename Schedulable, typename Rep, typename Period, typename F>\n  TimedTask schedule(\n      Schedulable& sched,\n      F&& func,\n      const std::chrono::duration<Rep, Period>& timeInFuture,\n      const std::chrono::duration<Rep, Period>& period,\n      size_t timesToRun = std::numeric_limits<size_t>::max(),\n      TimedTaskType type = TimedTaskType::kNormal) {\n    return schedule(\n        sched, std::forward<F>(func), toNextRun(timeInFuture), toPeriod(period), timesToRun, type);\n  }\n\n  /**\n   * Schedule a task to run periodically\n   *\n   * @param sched A backing schedulable, such as ImmediateInvoker, NewThreadInvoker, TaskSet, or\n   *        ThreadPool to run the function in when it is scheduled.\n   * @param func A bool() function to run when scheduled.  The function may return true to indicate\n   *        it should continue to be scheduled, or false to cancel.\n   * @param nextRunTime An absolute time to run the function.  If in the past, func will run\n   *        immediately.\n   * @param period The period defining the run frequency\n   * @param timesToRun The number of times to run the function.  After that number, the function\n   *        will not be called again.\n   * @param type The type of periodicity (if any).\n   **/\n  template <\n      typename Schedulable,\n      typename Rep,\n      typename Period,\n      typename Clock,\n      typename Duration,\n      typename F>\n  TimedTask schedule(\n      Schedulable& sched,\n      F&& func,\n      const std::chrono::time_point<Clock, Duration>& nextRunTime,\n      const std::chrono::duration<Rep, Period>& period,\n      size_t timesToRun = std::numeric_limits<size_t>::max(),\n      TimedTaskType type = TimedTaskType::kNormal) {\n    return schedule(\n        sched, std::forward<F>(func), toNextRun(nextRunTime), toPeriod(period), timesToRun, type);\n  }\n\n private:\n  template <class Rep, class Period>\n  static double toNextRun(const std::chrono::duration<Rep, Period>& timeInFuture) {\n    return getTime() + std::chrono::duration<double>(timeInFuture).count();\n  }\n\n  template <typename Clock, typename Duration>\n  static double toNextRun(const std::chrono::time_point<Clock, Duration>& nextRunTime) {\n    auto curTime = Clock::now();\n    return toNextRun(nextRunTime - curTime);\n  }\n\n  template <class Rep, class Period>\n  static double toPeriod(const std::chrono::duration<Rep, Period>& period) {\n    return std::chrono::duration<double>(period).count();\n  }\n  DISPENSO_DLL_ACCESS void addTimedTask(std::shared_ptr<detail::TimedTaskImpl> task);\n  void timeQueueRunLoop();\n\n  void kickOffTask(std::shared_ptr<detail::TimedTaskImpl> next, double curTime);\n\n  struct Compare {\n    bool operator()(\n        const std::shared_ptr<detail::TimedTaskImpl>& a,\n        const std::shared_ptr<detail::TimedTaskImpl>& b) const {\n      return a->nextAbsTime > b->nextAbsTime;\n    }\n  };\n\n  // TODO(bbudge): Consider lock-free priority queue implementation.  I'd expect it to be minimally\n  // beneficial for this use case though... timed tasks should rarely be super-high contention.\n  std::mutex queueMutex_;\n  std::priority_queue<\n      std::shared_ptr<detail::TimedTaskImpl>,\n      std::vector<std::shared_ptr<detail::TimedTaskImpl>>,\n      Compare>\n      tasks_;\n  bool running_{true};\n  detail::EpochWaiter epoch_;\n  std::thread thread_;\n  ThreadPriority priority_;\n};\n\n/**\n * Access the global timed task scheduler.  Most applications should only require one scheduler.\n *\n * @return A reference to the single instance global timed task scheduler.\n **/\nDISPENSO_DLL_ACCESS TimedTaskScheduler& globalTimedTaskScheduler();\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/timing.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/timing.h>\n\n#include <chrono>\n#include <cmath>\n\n#if defined(_MSC_VER)\n#include <intrin.h>\n#endif // _MSC_VER\n\n#if defined(_WIN32)\n#include <Windows.h>\n#endif // _WIN32\n\n#if defined(__MACH__)\n#include <mach/mach.h>\n#include <mach/mach_time.h>\n#endif // __MACH__\n\nnamespace dispenso {\nnamespace {\n#if defined(__x86_64__) || defined(_M_AMD64)\n#define DISPENSO_HAS_TIMESTAMP\n#if defined(_MSC_VER)\ninline uint64_t rdtscp() {\n  uint32_t ui;\n  return __rdtscp(&ui);\n}\n\n#else\ninline uint64_t rdtscp() {\n  uint32_t lo, hi;\n  __asm__ volatile(\"rdtscp\"\n                   : /* outputs */ \"=a\"(lo), \"=d\"(hi)\n                   : /* no inputs */\n                   : /* clobbers */ \"%rcx\");\n  return (uint64_t)lo | (((uint64_t)hi) << 32);\n}\n#endif // OS\n#elif (defined(__GNUC__) || defined(__clang__)) && defined(__aarch64__)\n#define DISPENSO_HAS_TIMESTAMP\nuint64_t rdtscp(void) {\n  uint64_t val;\n  __asm__ volatile(\"mrs %0, cntvct_el0\" : \"=r\"(val));\n  return val;\n}\n#endif // ARCH\n} // namespace\n\n#if defined(DISPENSO_HAS_TIMESTAMP)\n\n#if !defined(__aarch64__)\n\nstatic bool snapFreq(double& firstApprox) {\n  switch (static_cast<int>(firstApprox)) {\n    case 0:\n      if (std::abs(int(firstApprox * 10.0)) <= 1) {\n        firstApprox = 0.0;\n        return true;\n      }\n      break;\n    case 9:\n      if (std::abs(int(firstApprox * 10.0) - 99) <= 1) {\n        firstApprox = 10.0;\n\n        return true;\n      }\n      break;\n    case 3:\n      if (std::abs(int(firstApprox * 10.0) - 33) <= 1) {\n        firstApprox = 3.0 + 1.0 / 3.0;\n        return true;\n      }\n      break;\n    case 6:\n      if (std::abs(int(firstApprox * 10.0) - 66) <= 1) {\n        firstApprox = 6.0 + 2.0 / 3.0;\n        return true;\n      }\n      break;\n  }\n  return false;\n}\n\nstatic double fallbackTicksPerSecond() {\n  using namespace std::chrono_literals;\n  constexpr double kChronoOverheadBias = 250e-9;\n\n  auto baseStart = std::chrono::high_resolution_clock::now();\n  auto start = rdtscp();\n  std::this_thread::sleep_for(50ms);\n  auto end = rdtscp();\n  auto baseEnd = std::chrono::high_resolution_clock::now();\n\n  auto base = std::chrono::duration<double>(baseEnd - baseStart).count() - kChronoOverheadBias;\n  double firstApprox = (static_cast<double>(end - start)) / base;\n\n  // Try to refine the approximation.  In some circumstances we can \"snap\" the frequency to a very\n  // good guess that is off by less than one part in thousands.  Accuracy should already be quite\n  // good in any case, but this allows us to improve in some cases.\n\n  // Get first 3 digits\n  firstApprox *= 1e-7;\n\n  int firstInt = static_cast<int>(firstApprox);\n  firstApprox -= firstInt;\n\n  firstApprox *= 10.0;\n\n  if (!snapFreq(firstApprox)) {\n    int secondInt = static_cast<int>(firstApprox);\n    firstApprox -= secondInt;\n    firstApprox *= 10.0;\n    snapFreq(firstApprox);\n    firstApprox *= 0.1;\n    firstApprox += secondInt;\n  }\n\n  firstApprox *= 0.1;\n\n  firstApprox += firstInt;\n  firstApprox *= 1e7;\n  return firstApprox;\n}\n#endif // !__aarch64__\n\n#if defined(__aarch64__)\nstatic double ticksPerSecond() {\n  uint64_t val;\n  __asm__ volatile(\"mrs %0, cntfrq_el0\" : \"=r\"(val));\n  return static_cast<double>(val);\n}\n#elif defined(__MACH__)\nstatic double ticksPerSecond() {\n  mach_timebase_info_data_t info;\n  if (mach_timebase_info(&info) != KERN_SUCCESS) {\n    return fallbackTicksPerSecond();\n  }\n  return 1e9 * static_cast<double>(info.denom) / static_cast<double>(info.numer);\n}\n#else\ndouble ticksPerSecond() {\n  return fallbackTicksPerSecond();\n}\n#endif\n\ndouble getTime() {\n  static double secondsPerTick = 1.0 / ticksPerSecond();\n  static double startTime = static_cast<double>(rdtscp()) * secondsPerTick;\n\n  double t = static_cast<double>(rdtscp()) * secondsPerTick;\n  return t - startTime;\n}\n#else\ndouble getTime() {\n  static auto startTime = std::chrono::high_resolution_clock::now();\n  auto cur = std::chrono::high_resolution_clock::now();\n\n  return std::chrono::duration<double>(cur - startTime).count();\n}\n#endif // DISPENSO_HAS_TIMESTAMP\n\nnamespace {\n// This should ensure that we initialize the time before main.\ndouble g_dummyTime = getTime();\n} // namespace\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/timing.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file timing.h\n * @ingroup group_util\n * Utilities for getting the current time.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * Get elapsed time in seconds since program start.\n *\n * Uses high-resolution timing when available (e.g., RDTSC on x86).\n *\n * @return Elapsed time in seconds as a double.\n */\nDISPENSO_DLL_ACCESS double getTime();\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/tsan_annotations.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/tsan_annotations.h>\n\n#if DISPENSO_HAS_TSAN\n\n#ifdef __GNUC__\n#define ATTRIBUTE_WEAK __attribute__((weak))\n#else\n#define ATTRIBUTE_WEAK\n#endif\n\n// These are found in the accompanying libtsan, but there is no header exposing them.  We want to\n// also avoid exposing them in a header to to discourage folks from calling them directly.\nextern \"C\" {\nvoid AnnotateIgnoreReadsBegin(const char* f, int l) ATTRIBUTE_WEAK;\n\nvoid AnnotateIgnoreReadsEnd(const char* f, int l) ATTRIBUTE_WEAK;\n\nvoid AnnotateIgnoreWritesBegin(const char* f, int l) ATTRIBUTE_WEAK;\n\nvoid AnnotateIgnoreWritesEnd(const char* f, int l) ATTRIBUTE_WEAK;\n\nvoid AnnotateNewMemory(const char* f, int l, const volatile void* address, long size)\n    ATTRIBUTE_WEAK;\n\nvoid AnnotateHappensBefore(const char* f, int l, const volatile void* address) ATTRIBUTE_WEAK;\nvoid AnnotateHappensAfter(const char* f, int l, const volatile void* address) ATTRIBUTE_WEAK;\n}\n\nnamespace dispenso {\nnamespace detail {\n\nvoid annotateIgnoreWritesBegin(const char* f, int l) {\n  AnnotateIgnoreWritesBegin(f, l);\n}\nvoid annotateIgnoreWritesEnd(const char* f, int l) {\n  AnnotateIgnoreWritesEnd(f, l);\n}\nvoid annotateIgnoreReadsBegin(const char* f, int l) {\n  AnnotateIgnoreReadsBegin(f, l);\n}\nvoid annotateIgnoreReadsEnd(const char* f, int l) {\n  AnnotateIgnoreReadsEnd(f, l);\n}\n\nvoid annotateNewMemory(const char* f, int l, const volatile void* address, long size) {\n  AnnotateNewMemory(f, l, address, size);\n}\n\nvoid annotateHappensBefore(const char* f, int l, const volatile void* address) {\n  AnnotateHappensBefore(f, l, address);\n}\n\nvoid annotateHappensAfter(const char* f, int l, const volatile void* address) {\n  AnnotateHappensAfter(f, l, address);\n}\n\n} // namespace detail\n} // namespace dispenso\n\n#endif // TSAN\n"
  },
  {
    "path": "dispenso/tsan_annotations.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file tsan_annotations.h\n * @ingroup group_util\n * This file exposes a set of macros for ignoring tsan errors.  These should generally not\n * be used just to shut up TSAN, because most of the time, TSAN reports real bugs.  They should be\n * used only when there is a high level of certainty that TSAN is spitting out a false positive, as\n * can occasionally happen with lock-free algorithms.\n *\n * When these are required, it is best to keep the scope as small as possible to avoid blinding TSAN\n * to real bugs. Note that several libraries already expose macros like these, but we want to\n * keep dependencies to a bare minimum.\n **/\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n#if defined(__SANITIZE_THREAD__)\n#define DISPENSO_HAS_TSAN 1\n#elif defined(__has_feature)\n#if __has_feature(thread_sanitizer)\n#define DISPENSO_HAS_TSAN 1\n#else\n#define DISPENSO_HAS_TSAN 0\n#endif // TSAN\n#else\n#define DISPENSO_HAS_TSAN 0\n#endif // feature\n\n#if DISPENSO_HAS_TSAN\n\nnamespace dispenso {\nnamespace detail {\n\nDISPENSO_DLL_ACCESS void annotateIgnoreWritesBegin(const char* f, int l);\nDISPENSO_DLL_ACCESS void annotateIgnoreWritesEnd(const char* f, int l);\nDISPENSO_DLL_ACCESS void annotateIgnoreReadsBegin(const char* f, int l);\nDISPENSO_DLL_ACCESS void annotateIgnoreReadsEnd(const char* f, int l);\nDISPENSO_DLL_ACCESS void\nannotateNewMemory(const char* f, int l, const volatile void* address, long size);\nDISPENSO_DLL_ACCESS void annotateHappensBefore(const char* f, int l, const volatile void* address);\nDISPENSO_DLL_ACCESS void annotateHappensAfter(const char* f, int l, const volatile void* address);\n\n} // namespace detail\n} // namespace dispenso\n\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() \\\n  ::dispenso::detail::annotateIgnoreWritesBegin(__FILE__, __LINE__)\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END() \\\n  ::dispenso::detail::annotateIgnoreWritesEnd(__FILE__, __LINE__)\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_READS_BEGIN() \\\n  ::dispenso::detail::annotateIgnoreReadsBegin(__FILE__, __LINE__)\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_READS_END() \\\n  ::dispenso::detail::annotateIgnoreReadsEnd(__FILE__, __LINE__)\n#define DISPENSO_TSAN_ANNOTATE_NEW_MEMORY(address, size) \\\n  ::dispenso::detail::annotateNewMemory(__FILE__, __LINE__, address, size)\n#define DISPENSO_TSAN_ANNOTATE_HAPPENS_BEFORE(address) \\\n  ::dispenso::detail::annotateHappensBefore(__FILE__, __LINE__, address)\n#define DISPENSO_TSAN_ANNOTATE_HAPPENS_AFTER(address) \\\n  ::dispenso::detail::annotateHappensAfter(__FILE__, __LINE__, address)\n\n#else\n\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN()\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_WRITES_END()\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_READS_BEGIN()\n#define DISPENSO_TSAN_ANNOTATE_IGNORE_READS_END()\n#define DISPENSO_TSAN_ANNOTATE_NEW_MEMORY(address, size)\n#define DISPENSO_TSAN_ANNOTATE_HAPPENS_BEFORE(address)\n#define DISPENSO_TSAN_ANNOTATE_HAPPENS_AFTER(address)\n\n#endif // DISPENSO_HAS_TSAN\n"
  },
  {
    "path": "dispenso/util.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @file util.h\n * @ingroup group_util\n * A collection of utility functions and types for memory alignment, bit manipulation,\n * and performance optimization.\n *\n * @note The constant `kCacheLineSize` used by several utilities here is defined in\n *       `<dispenso/platform.h>`, which is included by this header.\n **/\n\n#pragma once\n\n#include <dispenso/detail/math.h>\n#include <dispenso/detail/op_result.h>\n#include <dispenso/platform.h>\n\nnamespace dispenso {\n\n/**\n * @brief Allocate memory with a specified alignment.\n *\n * This function allocates memory aligned to the specified boundary. The alignment\n * must be a power of 2 and at least sizeof(uintptr_t).\n *\n * @param bytes The number of bytes to allocate\n * @param alignment The alignment requirement in bytes (must be power of 2)\n * @return Pointer to aligned memory, or nullptr on allocation failure\n *\n * @note Memory allocated with alignedMalloc must be freed with alignedFree\n * @see alignedFree\n *\n * Example:\n * @code\n * void* ptr = dispenso::alignedMalloc(1024, 64);  // 64-byte aligned\n * // ... use ptr ...\n * dispenso::alignedFree(ptr);\n * @endcode\n */\ninline void* alignedMalloc(size_t bytes, size_t alignment) {\n  return detail::alignedMalloc(bytes, alignment);\n}\n\n/**\n * @brief Allocate memory aligned to cache line size.\n *\n * This is a convenience overload that aligns to kCacheLineSize (typically 64 bytes),\n * which helps avoid false sharing in concurrent data structures.\n *\n * @param bytes The number of bytes to allocate\n * @return Pointer to cache-line aligned memory, or nullptr on allocation failure\n *\n * @note Memory allocated with alignedMalloc must be freed with alignedFree\n * @see alignedFree, kCacheLineSize\n */\ninline void* alignedMalloc(size_t bytes) {\n  return detail::alignedMalloc(bytes);\n}\n\n/**\n * @brief Free memory allocated by alignedMalloc.\n *\n * @param ptr Pointer to memory allocated by alignedMalloc (can be nullptr)\n *\n * @see alignedMalloc\n */\ninline void alignedFree(void* ptr) {\n  detail::alignedFree(ptr);\n}\n\n/**\n * @brief Deleter for smart pointers that use aligned memory allocation.\n *\n * This deleter calls the destructor and frees memory allocated with alignedMalloc.\n * It can be used with std::unique_ptr and std::shared_ptr.\n *\n * @tparam T The type being deleted\n *\n * Example:\n * @code\n * using AlignedPtr = std::unique_ptr<MyType, dispenso::AlignedDeleter<MyType>>;\n * void* mem = dispenso::alignedMalloc(sizeof(MyType), 64);\n * AlignedPtr ptr(new (mem) MyType(), dispenso::AlignedDeleter<MyType>());\n * @endcode\n */\ntemplate <typename T>\nusing AlignedDeleter = detail::AlignedFreeDeleter<T>;\n\n/**\n * @brief Align a value up to the next cache line boundary.\n *\n * Rounds up the input value to the next multiple of kCacheLineSize. Useful for\n * manual memory layout to avoid false sharing.\n *\n * @param val The value to align\n * @return Value aligned to next cache line boundary\n *\n * @see kCacheLineSize\n *\n * Example:\n * @code\n * size_t offset = dispenso::alignToCacheLine(37);  // Returns 64\n * @endcode\n */\ninline constexpr uintptr_t alignToCacheLine(uintptr_t val) {\n  return detail::alignToCacheLine(val);\n}\n\n/**\n * @brief CPU relaxation hint for spin loops.\n *\n * Emits a platform-specific instruction (PAUSE on x86, YIELD on ARM) to improve\n * spin loop performance and reduce power consumption. Use this in busy-wait loops\n * to be friendlier to hyper-threading and the CPU pipeline.\n *\n * @note This is a no-op on platforms without a specific relax instruction\n *\n * Example:\n * @code\n * while (!flag.load(std::memory_order_acquire)) {\n *   dispenso::cpuRelax();  // Be nice to the CPU\n * }\n * @endcode\n */\ninline void cpuRelax() {\n  detail::cpuRelax();\n}\n\n/**\n * @brief Round up to the next power of 2.\n *\n * Computes the smallest power of 2 that is greater than or equal to the input value.\n *\n * @param v Input value\n * @return Next power of 2 (or v if v is already a power of 2)\n *\n * @note Returns 0 if v is 0\n *\n * Example:\n * @code\n * static_assert(dispenso::nextPow2(17) == 32);\n * static_assert(dispenso::nextPow2(64) == 64);\n * @endcode\n */\nconstexpr uint64_t nextPow2(uint64_t v) {\n  return detail::nextPow2(v);\n}\n\n/**\n * @brief Compute log base 2 of a value (compile-time).\n *\n * Computes floor(log2(v)) at compile time. Useful for template metaprogramming\n * and constexpr contexts.\n *\n * @param v Input value (must be > 0)\n * @return floor(log2(v))\n *\n * @note Behavior is undefined if v is 0\n *\n * Example:\n * @code\n * static_assert(dispenso::log2const(64) == 6);\n * static_assert(dispenso::log2const(100) == 6);\n * @endcode\n */\nconstexpr inline uint32_t log2const(uint64_t v) {\n  return detail::log2const(v);\n}\n\n/**\n * @brief Compute log base 2 of a value (runtime).\n *\n * Computes floor(log2(v)) using platform-specific intrinsics for optimal performance.\n * On x86/x64, uses __builtin_clzll or __lzcnt64. Falls back to constexpr version\n * on other platforms.\n *\n * @param v Input value (must be > 0)\n * @return floor(log2(v))\n *\n * @note Behavior is undefined if v is 0\n *\n * Example:\n * @code\n * uint32_t power = dispenso::log2(size);  // Fast bit scan\n * @endcode\n */\ninline uint32_t log2(uint64_t v) {\n  return detail::log2(v);\n}\n\n/**\n * @brief Buffer with proper alignment for type T.\n *\n * Provides uninitialized storage with proper alignment for type T. Useful for\n * manual object lifetime management or placement new scenarios.\n *\n * @tparam T The type to provide storage for\n *\n * Example:\n * @code\n * dispenso::AlignedBuffer<MyType> buf;\n * MyType* obj = new (buf.b) MyType();\n * obj->~MyType();\n * @endcode\n */\ntemplate <typename T>\nusing AlignedBuffer = detail::AlignedBuffer<T>;\n\n/**\n * @brief Cache-line aligned atomic pointer.\n *\n * An atomic pointer aligned to cache line boundary to avoid false sharing.\n * Inherits from std::atomic<T*>.\n *\n * @tparam T The pointed-to type\n *\n * Example:\n * @code\n * dispenso::AlignedAtomic<int> ptr;\n * ptr.store(new int(42));\n * @endcode\n */\ntemplate <typename T>\nusing AlignedAtomic = detail::AlignedAtomic<T>;\n\n/**\n * @brief Optional-like storage with in-place construction (C++14 compatible).\n *\n * Provides similar functionality to std::optional but works in C++14 codebases.\n * Stores the value in-place and tracks whether a value is present.\n *\n * @tparam T The type to store\n *\n * @note For small types, this has ~2x the size overhead of std::optional (pointer vs bool flag).\n *       For larger types, the overhead is similar. Prefer std::optional in C++17 and later.\n *\n * Example:\n * @code\n * dispenso::OpResult<int> result;\n * if (success) {\n *   result.emplace(42);\n * }\n * if (result) {\n *   use(result.value());\n * }\n * @endcode\n */\ntemplate <typename T>\nusing OpResult = detail::OpResult<T>;\n\n/**\n * @brief Information for statically chunking a range across threads.\n *\n * When dividing work into static chunks, using a simple chunk size plus remainder\n * can lead to poor load balancing. This struct provides the optimal chunking strategy\n * where some tasks get ceil(items/chunks) work and others get floor(items/chunks).\n */\nusing StaticChunking = detail::StaticChunking;\n\n/**\n * @brief Compute optimal static chunking for load balancing.\n *\n * Divides items into chunks such that the work is distributed as evenly as possible.\n * Returns chunking info where some tasks get ceil(items/chunks) and others get\n * floor(items/chunks).\n *\n * @param items Total number of items to process\n * @param chunks Number of chunks to divide into (must be > 0)\n * @return StaticChunking information for distributing the work\n *\n * Example:\n * @code\n * auto chunking = dispenso::staticChunkSize(100, 8);\n * // First 4 threads get 13 items each, last 4 get 12 items each\n * // 4*13 + 4*12 = 52 + 48 = 100\n * @endcode\n */\ninline StaticChunking staticChunkSize(ssize_t items, ssize_t chunks) {\n  return detail::staticChunkSize(items, chunks);\n}\n\n} // namespace dispenso\n"
  },
  {
    "path": "dispenso/utils/graph_dot.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/graph.h>\n#include <fstream>\n#include <string>\n#include <unordered_map>\n\nnamespace detail {\ninline std::string getName(\n    const void* ptr,\n    const size_t index,\n    const std::unordered_map<uintptr_t, std::string>* nodeNames) {\n  const uintptr_t key = reinterpret_cast<uintptr_t>(ptr);\n  if (nodeNames) {\n    auto it = nodeNames->find(key);\n    if (it != nodeNames->end()) {\n      return it->second;\n    }\n  }\n  return std::to_string(index);\n}\n} // namespace detail\n\nnamespace dispenso {\ntemplate <typename G>\nvoid graphsToDot(\n    const char* filename,\n    const G& graph,\n    const std::unordered_map<uintptr_t, std::string>* nodeNames) {\n  using SubgraphType = typename G::SubgraphType;\n  using NodeType = typename G::NodeType;\n  std::ofstream datfile(filename);\n  datfile << R\"dot(digraph {\n  rankdir = LR\n  node [shape = rectangle, style = filled, colorscheme=pastel19]\n  graph [style = filled, color = Gray95]\n\n  subgraph cluster_l { label = \"Legend\"; style=solid; color=black\n    empty1 [style = invis, shape=point]\n    empty2 [style = invis, shape=point]\n    incomplete [color = 1]\n    completed [color = 2]\n    incomplete -> empty1 [label = \"normal\"]\n    completed -> empty2 [arrowhead = onormal,label = \"bidirectional\\lpropagation\"]\n  }\n)dot\";\n\n  const size_t numSubgraphs = graph.numSubgraphs();\n  for (size_t i = 0; i < numSubgraphs; ++i) {\n    const SubgraphType& s = graph.subgraph(i);\n    if (i != 0) {\n      datfile << \"  \" << \"subgraph cluster_\" << i << \" { label = \\\"\"\n              << ::detail::getName(&s, i, nodeNames) << \"\\\"\\n\";\n    }\n    const size_t numNodes = s.numNodes();\n    for (size_t j = 0; j < numNodes; ++j) {\n      const NodeType& node = s.node(j);\n      datfile << \"    \" << reinterpret_cast<uintptr_t>(&node)\n              << \" [color = \" << (node.isCompleted() ? 2 : 1);\n      datfile << \" label = \\\"\" << ::detail::getName(&node, j, nodeNames) << \"\\\"]\\n\";\n    }\n\n    if (i != 0) {\n      datfile << \"  }\\n\";\n    }\n  }\n\n  graph.forEachNode([&](const NodeType& node) {\n    node.forEachDependent([&](const dispenso::Node& d) {\n      datfile << \"    \" << reinterpret_cast<uintptr_t>(&node) << \" -> \"\n              << reinterpret_cast<uintptr_t>(&d);\n\n      if (std::is_same<dispenso::BiPropNode, NodeType>::value) {\n        const auto& node1 = static_cast<const dispenso::BiPropNode&>(node);\n        const auto& node2 = static_cast<const dispenso::BiPropNode&>(d);\n        datfile << (node1.isSameSet(node2) ? \"[arrowhead=onormal]\" : \"\");\n      }\n      datfile << '\\n';\n    });\n  });\n\n  datfile << \"}\";\n  datfile.close();\n}\n} // namespace dispenso\n"
  },
  {
    "path": "docs/Doxyfile",
    "content": "# Doxyfile 1.8.14\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the config file\n# that follow. The default is UTF-8 which is also the encoding used for all text\n# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv\n# built into libc) for the transcoding. See\n# https://www.gnu.org/software/libiconv/ for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = dispenso\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         = 1.5.1\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"A library for task parallelism\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           = \n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = ./doxygen\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        = \n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    = \n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = NO\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 4\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines (in the resulting output). You can put ^^ in the value part of an\n# alias to insert a newline as if a physical newline was in the original file.\n\nALIASES                = \n\n# This tag can be used to specify a number of word-keyword mappings (TCL only).\n# A mapping has the form \"name=value\". For example adding \"class=itcl::class\"\n# will allow you to use the command class in the itcl::class meaning.\n\nTCL_SUBST              = \n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, Javascript,\n# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:\n# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:\n# Fortran. In the later case the parser tries to guess whether the code is fixed\n# or free formatted code, this is the default for Fortran type files), VHDL. For\n# instance to make doxygen treat .inc files as Fortran files (default is PHP),\n# and .f files as C (default is Fortran), use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen.\n\nEXTENSION_MAPPING      = \n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See http://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up\n# to that level are automatically included in the table of contents, even if\n# they do not have an id attribute.\n# Note: This feature currently applies only to Markdown headings.\n# Minimum value: 0, maximum value: 99, default value: 0.\n# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.\n\nTOC_INCLUDE_HEADINGS   = 0\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = NO\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# (class|struct|union) declarations. If set to NO, these declarations will be\n# included in the documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lower-case letters. If set to YES, upper-case letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = NO\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       = \n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    = \n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            = \n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         = \n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong or incomplete\n# parameter documentation, but not about the absence of documentation.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when\n# a warning is encountered.\n# The default value is: NO.\n\nWARN_AS_ERROR          = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           = doxygen_warnings.log\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = ../dispenso mainpage.md getting_started.md groups.dox\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: https://www.gnu.org/software/libiconv/) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,\n# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,\n# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,\n# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,\n# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.\n\nFILE_PATTERNS          = *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.inl \\\n                         *.markdown \\\n                         *.md \\\n                         *.dox\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = NO\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                = \n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       = dispenso::detail::*\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        = dispenso::detail::* \\\n                         *detail* \\\n                         DISPENSO_* \\\n                         TaskSetBase \\\n                         ChunkedRange \\\n                         ForceQueuingTag \\\n                         value_type \\\n                         reference \\\n                         const_reference \\\n                         size_type \\\n                         difference_type \\\n                         reference_type \\\n                         const_reference_type \\\n                         pointer \\\n                         const_pointer \\\n                         iterator \\\n                         const_iterator \\\n                         reverse_iterator \\\n                         const_reverse_iterator \\\n                         NodeType \\\n                         SubgraphType \\\n                         OpResult \\\n                         ssize_t \\\n                         kDefault* \\\n                         kImmediate* \\\n                         kNewThread* \\\n                         kCompleted \\\n                         kStatic \\\n                         ParentCascadeCancel \\\n                         operator== \\\n                         operator!= \\\n                         operator< \\\n                         operator> \\\n                         operator<= \\\n                         operator>= \\\n                         operator* \\\n                         \"operator new\" \\\n                         \"operator delete\" \\\n                         swap \\\n                         share \\\n                         then \\\n                         numIncompletePredecessors_ \\\n                         numPredecessors_ \\\n                         dependsOnOneNode \\\n                         DO_PRAGMA \\\n                         dispenso::cv::* \\\n                         *cv::* \\\n                         alloc \\\n                         dealloc\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           = ../examples\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *.cpp\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             = \n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nINPUT_FILTER           = \n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nFILTER_PATTERNS        = \n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS = \n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE = mainpage.md\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = YES\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# function all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see https://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the config file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in\n# which the alphabetical index list will be split.\n# Minimum value: 1, maximum value: 20, default value: 5.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nCOLS_IN_ALPHA_INDEX    = 5\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            = header.html\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            = \n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        = \n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list). For an example see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  = third-party/doxygen-awesome/doxygen-awesome.css custom.css\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       = third-party/doxygen-awesome/doxygen-awesome-darkmode-toggle.js\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# https://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 124\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = NO\n\n# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML\n# documentation will contain a main index with vertical navigation menus that\n# are dynamically created via Javascript. If disabled, the navigation index will\n# consists of multiple levels of tabs that are statically embedded in every HTML\n# page. Disable this option to support browsers that do not have Javascript,\n# like the Qt help browser.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_MENUS     = YES\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see: https://developer.apple.com/tools/xcode/), introduced with\n# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a\n# Makefile in the HTML output directory. Running make will produce the docset in\n# that directory and running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html\n# for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on\n# Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               = \n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           = \n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the master .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     = \n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               = \n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   = \n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  = \n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  = \n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           = \n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = YES\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANSPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# https://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from https://www.mathjax.org before deployment.\n# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     = \n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       = \n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using Javascript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: https://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: https://xapian.org/). See the section \"External Indexing and\n# Searching\" for details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       = \n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     = \n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when enabling USE_PDFLATEX this option is only used for generating\n# bitmaps for formulas in the HTML output, but not in the Makefile that is\n# written to the output directory.\n# The default file is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         = \n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber,\n# $projectbrief, $projectlogo. Doxygen will replace $title with the empty\n# string, for the replacement values of the other commands the user is referred\n# to HTML_HEADER.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           = \n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           = \n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET = \n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      = \n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate\n# the PDF file directly from the LaTeX files. Set this option to YES, to get a\n# higher quality PDF documentation.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# https://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated\n# page will contain the date and time when the page was generated. Setting this\n# to NO can help when comparing the output of multiple runs.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_TIMESTAMP        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's config\n# file, i.e. a series of assignments. You only have to provide replacements,\n# missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    = \n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's config file. A template extensions file can be generated\n# using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    = \n\n# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code\n# with syntax highlighting in the RTF output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_SOURCE_CODE        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             = \n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the\n# program listings (including syntax highlighting and cross-referencing\n# information) to the DOCBOOK output. Note that enabling this will significantly\n# increase the size of the DOCBOOK output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_PROGRAMLISTING = NO\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures\n# the structure of the code including all documentation. Note that this feature\n# is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           = .. \\\n                         ../dispenso/detail\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  = \n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             = __GNUC__\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      = \n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               = \n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       = \n\n# If the ALLEXTERNALS tag is set to YES, all external class will be listed in\n# the class index. If set to NO, only the inherited external classes will be\n# listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n# The PERL_PATH should be the absolute path and name of the perl script\n# interpreter (i.e. the result of 'which perl').\n# The default file (with absolute path) is: /usr/bin/perl.\n\nPERL_PATH              = /usr/bin/perl\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = NO\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            = \n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               = \n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font in the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           = \n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# http://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               = \n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           = \n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           = \n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           = \n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file. If left blank, it is assumed\n# PlantUML is not used or called during a preprocessing step. Doxygen will\n# generate a warning when it encounters a \\startuml command in this case and\n# will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      = \n\n# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a\n# configuration file for plantuml.\n\nPLANTUML_CFG_FILE      = \n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  = \n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "docs/benchmarks/benchmark_results.md",
    "content": "# Dispenso Benchmark Results\n\n## Machine Information\n\n- **Date**: 2026-02-05T15:59:21.769268\n- **Platform**: Linux 6.17.4-200.fc42.x86_64\n- **CPU**: AMD Ryzen Threadripper PRO 7995WX 96-Cores\n- **Hardware Threads**: 192\n- **Memory**: 250.9 GB\n\n## Results Summary\n\n- **Benchmarks run**: 18\n- **Successful**: 18\n- **Failed**: 0\n\n### concurrent_vector\n\n**Serial/Access Operations:**\n\n![concurrent_vector serial](concurrent_vector_serial_chart.png)\n\n**Parallel Operations:**\n\n![concurrent_vector parallel](concurrent_vector_parallel_chart.png)\n\n[View detailed results table](concurrent_vector_details.md)\n\n### for_latency\n\n**default elements:**\n\n![for_latency default](for_latency_default_chart.png)\n\n[View detailed results table](for_latency_details.md)\n\n### future\n\n**Full comparison (including std::async):**\n\n![future results](future_chart.png)\n\n**Zoomed (excluding std::async):**\n\n![future zoomed](future_zoomed_chart.png)\n\n[View detailed results table](future_details.md)\n\n### graph\n\n![graph results](graph_chart.png)\n\n[View detailed results table](graph_details.md)\n\n### graph_scene\n\n![graph_scene results](graph_scene_chart.png)\n\n[View detailed results table](graph_scene_details.md)\n\n### idle_pool\n\n**default elements:**\n\n![idle_pool default](idle_pool_default_chart.png)\n\n**1K elements:**\n\n![idle_pool 1K](idle_pool_1000_chart.png)\n\n**10K elements:**\n\n![idle_pool 10K](idle_pool_10000_chart.png)\n\n**1M elements:**\n\n![idle_pool 1M](idle_pool_1000000_chart.png)\n\n[View detailed results table](idle_pool_details.md)\n\n### nested_for\n\n**10 elements:**\n\n![nested_for 10](nested_for_10_chart.png)\n\n**10 elements (Y-Axis Zoomed):**\n\n![nested_for 10 zoomed](nested_for_10_zoomed_chart.png)\n\n**500 elements:**\n\n![nested_for 500](nested_for_500_chart.png)\n\n**500 elements (Y-Axis Zoomed):**\n\n![nested_for 500 zoomed](nested_for_500_zoomed_chart.png)\n\n**3K elements:**\n\n![nested_for 3K](nested_for_3000_chart.png)\n\n**3K elements (Y-Axis Zoomed):**\n\n![nested_for 3K zoomed](nested_for_3000_zoomed_chart.png)\n\n[View detailed results table](nested_for_details.md)\n\n### nested_pool\n\n**1K elements:**\n\n![nested_pool 1K](nested_pool_1000_chart.png)\n\n**10K elements:**\n\n![nested_pool 10K](nested_pool_10000_chart.png)\n\n**1M elements:**\n\n![nested_pool 1M](nested_pool_1000000_chart.png)\n\n*Note: folly::CPUThreadPoolExecutor is excluded from the 1M chart as it fails to complete (likely due to memory exhaustion from creating too many futures).*\n\n[View detailed results table](nested_pool_details.md)\n\n### once_function\n\n**Move Operations:**\n\n![once_function move](once_function_move_chart.png)\n\n**Queue Operations:**\n\n![once_function queue](once_function_queue_chart.png)\n\n[View detailed results table](once_function_details.md)\n\n### pipeline\n\n![pipeline results](pipeline_chart.png)\n\n[View detailed results table](pipeline_details.md)\n\n### pool_allocator\n\n**Single-threaded:**\n\n![pool_allocator 1t](pool_allocator_1t_chart.png)\n\n**2 Threads:**\n\n![pool_allocator 2t](pool_allocator_2t_chart.png)\n\n**8 Threads:**\n\n![pool_allocator 8t](pool_allocator_8t_chart.png)\n\n**16 Threads:**\n\n![pool_allocator 16t](pool_allocator_16t_chart.png)\n\n[View detailed results table](pool_allocator_details.md)\n\n### rw_lock\n\n**Serial Operations:**\n\n![rw_lock serial](rw_lock_serial_chart.png)\n\n**Parallel Operations:**\n\n**2 Iterations:**\n\n![rw_lock parallel 2](rw_lock_parallel_2_chart.png)\n\n**8 Iterations:**\n\n![rw_lock parallel 8](rw_lock_parallel_8_chart.png)\n\n**32 Iterations:**\n\n![rw_lock parallel 32](rw_lock_parallel_32_chart.png)\n\n**128 Iterations:**\n\n![rw_lock parallel 128](rw_lock_parallel_128_chart.png)\n\n**512 Iterations:**\n\n![rw_lock parallel 512](rw_lock_parallel_512_chart.png)\n\n[View detailed results table](rw_lock_details.md)\n\n### simple_for\n\n**1K elements:**\n\n![simple_for 1K](simple_for_1000_chart.png)\n\n**1K elements (Y-Axis Zoomed):**\n\n![simple_for 1K zoomed](simple_for_1000_zoomed_chart.png)\n\n**1M elements:**\n\n![simple_for 1M](simple_for_1000000_chart.png)\n\n**1M elements (Y-Axis Zoomed):**\n\n![simple_for 1M zoomed](simple_for_1000000_zoomed_chart.png)\n\n**100M elements:**\n\n![simple_for 100M](simple_for_100000000_chart.png)\n\n**100M elements (Y-Axis Zoomed):**\n\n![simple_for 100M zoomed](simple_for_100000000_zoomed_chart.png)\n\n[View detailed results table](simple_for_details.md)\n\n### simple_pool\n\n**1K elements:**\n\n![simple_pool 1K](simple_pool_1000_chart.png)\n\n**10K elements:**\n\n![simple_pool 10K](simple_pool_10000_chart.png)\n\n**1M elements:**\n\n![simple_pool 1M](simple_pool_1000000_chart.png)\n\n[View detailed results table](simple_pool_details.md)\n\n### small_buffer\n\n![small_buffer results](small_buffer_chart.png)\n\n[View detailed results table](small_buffer_details.md)\n\n### summing_for\n\n**1K elements:**\n\n![summing_for 1K](summing_for_1000_chart.png)\n\n**1K elements (Y-Axis Zoomed):**\n\n![summing_for 1K zoomed](summing_for_1000_zoomed_chart.png)\n\n**1M elements:**\n\n![summing_for 1M](summing_for_1000000_chart.png)\n\n**1M elements (Y-Axis Zoomed):**\n\n![summing_for 1M zoomed](summing_for_1000000_zoomed_chart.png)\n\n**100M elements:**\n\n![summing_for 100M](summing_for_100000000_chart.png)\n\n**100M elements (Y-Axis Zoomed):**\n\n![summing_for 100M zoomed](summing_for_100000000_zoomed_chart.png)\n\n[View detailed results table](summing_for_details.md)\n\n### timed_task\n\n*Visualization not available for this benchmark.*\n\n[View detailed results table](timed_task_details.md)\n\n### trivial_compute\n\n**100 elements:**\n\n![trivial_compute 100](trivial_compute_100_chart.png)\n\n**100 elements (Y-Axis Zoomed):**\n\n![trivial_compute 100 zoomed](trivial_compute_100_zoomed_chart.png)\n\n**1M elements:**\n\n![trivial_compute 1M](trivial_compute_1000000_chart.png)\n\n**1M elements (Y-Axis Zoomed):**\n\n![trivial_compute 1M zoomed](trivial_compute_1000000_zoomed_chart.png)\n\n**100M elements:**\n\n![trivial_compute 100M](trivial_compute_100000000_chart.png)\n\n**100M elements (Y-Axis Zoomed):**\n\n![trivial_compute 100M zoomed](trivial_compute_100000000_zoomed_chart.png)\n\n[View detailed results table](trivial_compute_details.md)\n\n"
  },
  {
    "path": "docs/benchmarks/concurrent_vector_details.md",
    "content": "# concurrent_vector - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso_parallel_grow_by_max | 101003.60 | ns | 7188 |\n| BM_std_index | 106858.12 | ns | 6725 |\n| BM_std_iterate_reverse | 110684.51 | ns | 6546 |\n| BM_std_iterate | 111485.94 | ns | 6353 |\n| BM_std_push_back_serial_reserve | 218703.74 | ns | 3249 |\n| BM_dispenso_push_back_serial_grow_by_alternative_reserve | 219040.99 | ns | 3285 |\n| BM_dispenso_push_back_serial_grow_by_alternative | 219550.30 | ns | 3271 |\n| BM_dispenso_iterate_reverse | 255835.84 | ns | 2759 |\n| BM_dispenso_parallel_grow_by_100 | 306185.16 | ns | 2330 |\n| BM_dispenso_iterate | 325710.90 | ns | 2210 |\n| BM_deque_iterate | 391508.18 | ns | 1703 |\n| BM_deque_push_back_serial | 394323.34 | ns | 1781 |\n| BM_deque_iterate_reverse | 398834.15 | ns | 1735 |\n| BM_tbb_index | 554215.73 | ns | 1220 |\n| BM_tbb_iterate | 642360.91 | ns | 1077 |\n| BM_deque_index | 669881.35 | ns | 1105 |\n| BM_tbb_parallel_grow_by_max | 726051.72 | ns | 981 |\n| BM_std_random | 785495.08 | ns | 904 |\n| BM_dispenso_index | 901852.14 | ns | 757 |\n| BM_tbb_iterate_reverse | 1272616.17 | ns | 558 |\n| BM_tbb_random | 1292540.94 | ns | 560 |\n| BM_deque_random | 1619131.51 | ns | 465 |\n| BM_dispenso_push_back_serial_reserve | 1823914.35 | ns | 369 |\n| BM_tbb_parallel_grow_by_100 | 2081724.50 | ns | 364 |\n| BM_deque_parallel_grow_by_max | 2712039.31 | ns | 426 |\n| BM_std_push_back_serial | 2850313.38 | ns | 243 |\n| BM_std_parallel_grow_by_max | 2883582.54 | ns | 405 |\n| BM_dispenso_parallel_grow_by_10 | 2969110.81 | ns | 260 |\n| BM_dispenso_random | 2982333.81 | ns | 247 |\n| BM_tbb_push_back_serial_grow_by_alternative | 3372009.29 | ns | 207 |\n| BM_tbb_push_back_serial_grow_by_alternative_reserve | 3425661.25 | ns | 209 |\n| BM_tbb_push_back_serial | 4311813.53 | ns | 156 |\n| BM_tbb_push_back_serial_reserve | 4413419.62 | ns | 165 |\n| BM_dispenso_push_back_serial | 5946197.95 | ns | 112 |\n| BM_tbb_parallel_grow_by_10 | 7933075.11 | ns | 90 |\n| BM_std_parallel_grow_by_100 | 13813984.13 | ns | 54 |\n| BM_deque_parallel_grow_by_100 | 17067703.38 | ns | 100 |\n| BM_std_lower_bound | 26307376.03 | ns | 27 |\n| BM_dispenso_parallel_clear | 26754469.40 | ns | 26 |\n| BM_dispenso_parallel_reserve | 27197122.78 | ns | 27 |\n| BM_std_parallel_grow_by_10 | 31354538.79 | ns | 24 |\n| BM_dispenso_lower_bound | 33074250.53 | ns | 21 |\n| BM_deque_lower_bound | 34870844.87 | ns | 21 |\n| BM_dispenso_parallel | 35100432.49 | ns | 20 |\n| BM_tbb_lower_bound | 35831723.10 | ns | 21 |\n| BM_deque_parallel_grow_by_10 | 37788011.33 | ns | 19 |\n| BM_tbb_parallel | 44999558.13 | ns | 16 |\n| BM_tbb_parallel_reserve | 45318455.78 | ns | 16 |\n| BM_tbb_parallel_clear | 45865617.69 | ns | 16 |\n| BM_std_parallel_reserve | 110097669.38 | ns | 6 |\n| BM_std_parallel_clear | 116452485.01 | ns | 6 |\n| BM_std_parallel | 122873134.17 | ns | 5 |\n| BM_deque_parallel | 130722294.75 | ns | 5 |\n| BM_deque_parallel_clear | 133983735.74 | ns | 5 |\n"
  },
  {
    "path": "docs/benchmarks/concurrent_vector_tcmalloc_details.md",
    "content": "# concurrent_vector_tcmalloc - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso_parallel_grow_by_max | 94711.39 | ns | 7194 |\n| BM_std_index | 109426.63 | ns | 6719 |\n| BM_std_iterate_reverse | 109865.98 | ns | 6654 |\n| BM_std_iterate | 110317.93 | ns | 6742 |\n| BM_std_push_back_serial_reserve | 220767.06 | ns | 3228 |\n| BM_dispenso_push_back_serial_grow_by_alternative_reserve | 225284.88 | ns | 3330 |\n| BM_dispenso_push_back_serial_grow_by_alternative | 226044.39 | ns | 3222 |\n| BM_dispenso_iterate_reverse | 252425.97 | ns | 2869 |\n| BM_std_push_back_serial | 296661.69 | ns | 2471 |\n| BM_deque_push_back_serial | 315272.88 | ns | 2116 |\n| BM_dispenso_iterate | 321445.97 | ns | 2302 |\n| BM_dispenso_parallel_grow_by_100 | 327465.75 | ns | 2166 |\n| BM_deque_iterate | 393058.36 | ns | 1828 |\n| BM_deque_iterate_reverse | 408638.55 | ns | 1777 |\n| BM_tbb_index | 557577.77 | ns | 1333 |\n| BM_tbb_iterate | 642920.27 | ns | 1133 |\n| BM_deque_index | 665543.73 | ns | 1104 |\n| BM_tbb_parallel_grow_by_max | 694381.15 | ns | 1020 |\n| BM_std_random | 814733.74 | ns | 830 |\n| BM_dispenso_index | 881164.69 | ns | 811 |\n| BM_tbb_random | 1254265.98 | ns | 585 |\n| BM_tbb_iterate_reverse | 1341082.67 | ns | 556 |\n| BM_deque_random | 1555339.24 | ns | 437 |\n| BM_dispenso_push_back_serial_reserve | 1811815.80 | ns | 408 |\n| BM_tbb_parallel_grow_by_100 | 2042351.42 | ns | 363 |\n| BM_dispenso_parallel_grow_by_10 | 2858888.56 | ns | 254 |\n| BM_dispenso_random | 2966586.89 | ns | 241 |\n| BM_std_parallel_grow_by_max | 2997329.75 | ns | 394 |\n| BM_tbb_push_back_serial_grow_by_alternative | 3401108.28 | ns | 211 |\n| BM_tbb_push_back_serial_grow_by_alternative_reserve | 3436731.78 | ns | 211 |\n| BM_deque_parallel_grow_by_max | 3786375.45 | ns | 302 |\n| BM_tbb_push_back_serial | 4419180.69 | ns | 154 |\n| BM_tbb_push_back_serial_reserve | 4477015.58 | ns | 160 |\n| BM_dispenso_push_back_serial | 4656596.25 | ns | 147 |\n| BM_tbb_parallel_grow_by_10 | 7976818.67 | ns | 93 |\n| BM_std_parallel_grow_by_100 | 14841504.28 | ns | 50 |\n| BM_deque_parallel_grow_by_100 | 16374853.73 | ns | 188 |\n| BM_dispenso_parallel | 27056859.12 | ns | 27 |\n| BM_dispenso_parallel_reserve | 27211764.04 | ns | 26 |\n| BM_std_lower_bound | 27674214.70 | ns | 26 |\n| BM_dispenso_parallel_clear | 27796568.97 | ns | 27 |\n| BM_std_parallel_grow_by_10 | 32000467.83 | ns | 23 |\n| BM_dispenso_lower_bound | 33722069.29 | ns | 21 |\n| BM_tbb_lower_bound | 35792074.91 | ns | 20 |\n| BM_deque_lower_bound | 36033107.23 | ns | 21 |\n| BM_deque_parallel_grow_by_10 | 39033348.15 | ns | 18 |\n| BM_tbb_parallel | 45672182.23 | ns | 16 |\n| BM_tbb_parallel_reserve | 45781568.86 | ns | 16 |\n| BM_tbb_parallel_clear | 45881552.04 | ns | 16 |\n| BM_std_parallel_reserve | 109698760.19 | ns | 7 |\n| BM_std_parallel_clear | 113008682.93 | ns | 6 |\n| BM_std_parallel | 116849953.00 | ns | 6 |\n| BM_deque_parallel_clear | 118793300.97 | ns | 6 |\n| BM_deque_parallel | 119249812.02 | ns | 6 |\n"
  },
  {
    "path": "docs/benchmarks/for_latency_details.md",
    "content": "# for_latency - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_tbb/128/real_time | 30671103.82 | ns | 23 |\n| BM_tbb/64/real_time | 30684292.48 | ns | 23 |\n| BM_tbb/192/real_time | 30727495.24 | ns | 23 |\n| BM_dispenso/192/real_time | 30787112.84 | ns | 23 |\n| BM_tbb/96/real_time | 30845612.29 | ns | 23 |\n| BM_tbb/32/real_time | 30862872.61 | ns | 23 |\n| BM_tbb/24/real_time | 30868742.29 | ns | 23 |\n| BM_dispenso/96/real_time | 30869602.35 | ns | 23 |\n| BM_dispenso/128/real_time | 30870548.09 | ns | 23 |\n| BM_tbb/48/real_time | 30880625.89 | ns | 23 |\n| BM_omp/32/real_time | 30903007.35 | ns | 23 |\n| BM_dispenso/64/real_time | 30907894.77 | ns | 23 |\n| BM_dispenso/48/real_time | 30912572.19 | ns | 23 |\n| BM_omp/48/real_time | 30921780.38 | ns | 23 |\n| BM_tbb/16/real_time | 30985629.11 | ns | 23 |\n| BM_omp/64/real_time | 31000481.11 | ns | 23 |\n| BM_omp/24/real_time | 31005283.17 | ns | 23 |\n| BM_tbb/12/real_time | 31025142.61 | ns | 23 |\n| BM_dispenso/32/real_time | 31051012.77 | ns | 22 |\n| BM_tbb/8/real_time | 31081565.78 | ns | 23 |\n| BM_dispenso/24/real_time | 31084572.49 | ns | 23 |\n| BM_omp/16/real_time | 31089434.64 | ns | 23 |\n| BM_omp/96/real_time | 31202504.49 | ns | 23 |\n| BM_dispenso/16/real_time | 31203918.07 | ns | 22 |\n| BM_omp/12/real_time | 31261700.12 | ns | 22 |\n| BM_tbb/6/real_time | 31310660.09 | ns | 22 |\n| BM_dispenso/8/real_time | 31360803.76 | ns | 22 |\n| BM_dispenso/12/real_time | 31397428.45 | ns | 22 |\n| BM_omp/8/real_time | 31440352.17 | ns | 22 |\n| BM_omp/6/real_time | 31527165.15 | ns | 22 |\n| BM_omp/128/real_time | 31648196.10 | ns | 21 |\n| BM_tbb/4/real_time | 31666634.27 | ns | 22 |\n| BM_dispenso/6/real_time | 31692434.02 | ns | 22 |\n| BM_omp/4/real_time | 31863744.29 | ns | 22 |\n| BM_tbb/3/real_time | 31948655.25 | ns | 22 |\n| BM_omp/3/real_time | 32270322.81 | ns | 22 |\n| BM_dispenso/4/real_time | 32570220.18 | ns | 21 |\n| BM_tbb/2/real_time | 32705506.75 | ns | 21 |\n| BM_omp/2/real_time | 32883003.00 | ns | 21 |\n| BM_dispenso/3/real_time | 33338752.18 | ns | 21 |\n| BM_dispenso/2/real_time | 34245214.15 | ns | 20 |\n| BM_dispenso/1/real_time | 34983571.99 | ns | 20 |\n| BM_serial/real_time | 35045663.45 | ns | 20 |\n| BM_omp/1/real_time | 35077819.41 | ns | 20 |\n| BM_omp/192/real_time | 35145964.01 | ns | 20 |\n| BM_tbb/1/real_time | 35147623.07 | ns | 20 |\n"
  },
  {
    "path": "docs/benchmarks/future_details.md",
    "content": "# future - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_serial_tree<kSmallSize>/real_time | 316423.21 | ns | 2182 |\n| BM_dispenso_taskset_tree<kSmallSize>/real_time | 666544.19 | ns | 1197 |\n| BM_dispenso_tree<kSmallSize>/real_time | 941047.69 | ns | 720 |\n| BM_dispenso_tree_when_all<kSmallSize>/real_time | 980887.75 | ns | 678 |\n| BM_folly_tree<kSmallSize>/real_time | 1910670.03 | ns | 346 |\n| BM_serial_tree<kMediumSize>/real_time | 2494288.26 | ns | 277 |\n| BM_dispenso_taskset_tree<kMediumSize>/real_time | 2542309.12 | ns | 279 |\n| BM_dispenso_tree<kMediumSize>/real_time | 4200437.39 | ns | 167 |\n| BM_dispenso_tree_when_all<kMediumSize>/real_time | 4399805.82 | ns | 159 |\n| BM_folly_tree<kMediumSize>/real_time | 10451328.26 | ns | 60 |\n| BM_dispenso_taskset_tree<kLargeSize>/real_time | 13767162.49 | ns | 50 |\n| BM_serial_tree<kLargeSize>/real_time | 20290996.29 | ns | 35 |\n| BM_dispenso_tree<kLargeSize>/real_time | 25793796.47 | ns | 28 |\n| BM_dispenso_tree_when_all<kLargeSize>/real_time | 28994647.40 | ns | 24 |\n| BM_folly_tree<kLargeSize>/real_time | 75235617.35 | ns | 8 |\n| BM_std_tree<kSmallSize>/real_time | 174957101.54 | ns | 3 |\n| BM_std_tree<kMediumSize>/real_time | 1593472268.43 | ns | 1 |\n| BM_std_tree<kLargeSize>/real_time | 22856111893.43 | ns | 1 |\n"
  },
  {
    "path": "docs/benchmarks/graph_details.md",
    "content": "# graph - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_build_bi_prop_dependency_group | 430.35 | ns | 1567773 |\n| BM_execute_dependency_chain<dispenso::Graph> | 7832.33 | ns | 91950 |\n| BM_execute_dependency_chain<dispenso::BiPropGraph> | 7881.34 | ns | 90236 |\n| BM_build_dependency_chain<dispenso::Graph> | 17572.99 | ns | 39706 |\n| BM_build_dependency_chain<dispenso::BiPropGraph> | 18148.89 | ns | 39736 |\n| BM_build_bi_prop_dependency_chain | 44498.37 | ns | 15908 |\n| BM_forward_propagator_node<dispenso::Graph> | 1428797.45 | ns | 486 |\n| BM_forward_propagator_node<dispenso::BiPropGraph> | 1463463.54 | ns | 480 |\n| BM_build_big_tree<dispenso::BiPropGraph> | 1535004.83 | ns | 463 |\n| BM_build_big_tree<dispenso::Graph> | 1728478.59 | ns | 411 |\n| BM_taskflow_build_big_tree | 2741159.89 | ns | 247 |\n"
  },
  {
    "path": "docs/benchmarks/graph_scene_details.md",
    "content": "# graph_scene - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_scene_graph_partial_revaluation/real_time | 756865.19 | ns | 932 |\n| BM_scene_graph_parallel_for/real_time | 11785746.10 | ns | 58 |\n| BM_scene_graph_taskflow/real_time | 12178284.88 | ns | 67 |\n| BM_scene_graph_concurrent_task_set/real_time | 12321619.66 | ns | 59 |\n"
  },
  {
    "path": "docs/benchmarks/idle_pool_details.md",
    "content": "# idle_pool - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_tbb_mostly_idle/1/1000/real_time | 28.13 | us | 24863 |\n| BM_tbb_mostly_idle/2/1000/real_time | 28.78 | us | 23604 |\n| BM_tbb_mostly_idle/3/1000/real_time | 29.73 | us | 23330 |\n| BM_tbb_mostly_idle/4/1000/real_time | 31.36 | us | 22399 |\n| BM_tbb_mostly_idle/6/1000/real_time | 33.99 | us | 20203 |\n| BM_tbb_mostly_idle/8/1000/real_time | 38.64 | us | 17549 |\n| BM_tbb_mostly_idle/12/1000/real_time | 53.63 | us | 11821 |\n| BM_dispenso_mostly_idle/1/1000/real_time | 54.49 | us | 12961 |\n| BM_dispenso_mostly_idle/2/1000/real_time | 54.80 | us | 12822 |\n| BM_tbb_mostly_idle/16/1000/real_time | 70.06 | us | 10541 |\n| BM_dispenso_mostly_idle/3/1000/real_time | 85.46 | us | 8101 |\n| BM_dispenso_mostly_idle/4/1000/real_time | 116.65 | us | 6034 |\n| BM_tbb_mostly_idle/24/1000/real_time | 117.01 | us | 5711 |\n| BM_tbb_mostly_idle/32/1000/real_time | 169.01 | us | 3924 |\n| BM_dispenso_mostly_idle/6/1000/real_time | 189.33 | us | 3749 |\n| BM_tbb_mostly_idle/1/10000/real_time | 249.67 | us | 2777 |\n| BM_tbb_mostly_idle/2/10000/real_time | 262.80 | us | 2678 |\n| BM_tbb_mostly_idle/3/10000/real_time | 275.62 | us | 2526 |\n| BM_dispenso_mostly_idle/1/10000/real_time | 296.07 | us | 2364 |\n| BM_tbb_mostly_idle/4/10000/real_time | 296.50 | us | 2430 |\n| BM_dispenso_mostly_idle/2/10000/real_time | 298.61 | us | 2374 |\n| BM_tbb_mostly_idle/48/1000/real_time | 301.86 | us | 2255 |\n| BM_dispenso_mostly_idle/8/1000/real_time | 304.32 | us | 2296 |\n| BM_tbb_mostly_idle/6/10000/real_time | 322.27 | us | 2073 |\n| BM_dispenso_mostly_idle/3/10000/real_time | 328.85 | us | 2115 |\n| BM_dispenso_mostly_idle/4/10000/real_time | 401.27 | us | 1721 |\n| BM_tbb_mostly_idle/8/10000/real_time | 413.26 | us | 1371 |\n| BM_tbb_mostly_idle/64/1000/real_time | 436.96 | us | 1620 |\n| BM_dispenso_mostly_idle/12/1000/real_time | 518.76 | us | 1360 |\n| BM_dispenso_mostly_idle/6/10000/real_time | 535.27 | us | 1275 |\n| BM_dispenso_mostly_idle/8/10000/real_time | 591.77 | us | 1191 |\n| BM_tbb_mostly_idle/96/1000/real_time | 697.71 | us | 995 |\n| BM_tbb_mostly_idle/12/10000/real_time | 719.68 | us | 808 |\n| BM_dispenso_mostly_idle/16/1000/real_time | 734.50 | us | 943 |\n| BM_dispenso_mostly_idle/12/10000/real_time | 892.62 | us | 825 |\n| BM_tbb_mostly_idle/128/1000/real_time | 977.00 | us | 716 |\n| BM_tbb_mostly_idle/16/10000/real_time | 1007.70 | us | 671 |\n| BM_dispenso_mostly_idle/24/1000/real_time | 1150.27 | us | 618 |\n| BM_dispenso_mostly_idle/16/10000/real_time | 1164.93 | us | 625 |\n| BM_tbb_mostly_idle/192/1000/real_time | 1443.46 | us | 521 |\n| BM_dispenso_mostly_idle/32/1000/real_time | 1589.50 | us | 433 |\n| BM_dispenso_mostly_idle/24/10000/real_time | 1611.86 | us | 435 |\n| BM_tbb_mostly_idle/24/10000/real_time | 2100.22 | us | 332 |\n| BM_dispenso_mostly_idle/32/10000/real_time | 2129.78 | us | 333 |\n| BM_dispenso_mostly_idle/48/1000/real_time | 2431.86 | us | 279 |\n| BM_tbb_mostly_idle/32/10000/real_time | 2489.99 | us | 274 |\n| BM_dispenso_mostly_idle/48/10000/real_time | 3000.61 | us | 229 |\n| BM_dispenso_mostly_idle/64/1000/real_time | 3347.02 | us | 205 |\n| BM_tbb_mostly_idle/48/10000/real_time | 3833.92 | us | 188 |\n| BM_dispenso_mostly_idle/64/10000/real_time | 4348.10 | us | 161 |\n| BM_tbb_mostly_idle/64/10000/real_time | 4752.66 | us | 145 |\n| BM_dispenso_mostly_idle/96/1000/real_time | 5231.94 | us | 135 |\n| BM_dispenso_mostly_idle/96/10000/real_time | 5953.73 | us | 129 |\n| BM_dispenso_mostly_idle/128/1000/real_time | 7138.42 | us | 102 |\n| BM_tbb_mostly_idle/96/10000/real_time | 7776.04 | us | 95 |\n| BM_dispenso_mostly_idle/128/10000/real_time | 8442.95 | us | 84 |\n| BM_tbb_mostly_idle/128/10000/real_time | 10351.21 | us | 67 |\n| BM_dispenso_mostly_idle/192/1000/real_time | 10740.92 | us | 68 |\n| BM_tbb_mostly_idle/192/10000/real_time | 10748.11 | us | 83 |\n| BM_dispenso_mostly_idle/192/10000/real_time | 12548.88 | us | 52 |\n| BM_tbb_mostly_idle/1/1000000/real_time | 24101.02 | us | 29 |\n| BM_tbb_mostly_idle/2/1000000/real_time | 25146.24 | us | 27 |\n| BM_dispenso_mostly_idle/1/1000000/real_time | 25780.46 | us | 27 |\n| BM_dispenso_mostly_idle/2/1000000/real_time | 25806.83 | us | 26 |\n| BM_dispenso_mostly_idle/4/1000000/real_time | 26408.81 | us | 26 |\n| BM_dispenso_mostly_idle/3/1000000/real_time | 26478.24 | us | 26 |\n| BM_tbb_mostly_idle/4/1000000/real_time | 27791.26 | us | 25 |\n| BM_dispenso_mostly_idle/6/1000000/real_time | 27828.24 | us | 26 |\n| BM_tbb_mostly_idle/3/1000000/real_time | 28087.34 | us | 27 |\n| BM_tbb_mostly_idle/6/1000000/real_time | 31796.60 | us | 21 |\n| BM_dispenso_mostly_idle/8/1000000/real_time | 37281.95 | us | 20 |\n| BM_dispenso_mostly_idle/16/1000000/real_time | 41165.59 | us | 14 |\n| BM_tbb_mostly_idle/8/1000000/real_time | 44492.20 | us | 18 |\n| BM_dispenso_mostly_idle/12/1000000/real_time | 57657.43 | us | 10 |\n| BM_dispenso_mostly_idle/24/1000000/real_time | 62123.15 | us | 10 |\n| BM_dispenso_mostly_idle/32/1000000/real_time | 66075.62 | us | 16 |\n| BM_tbb_mostly_idle/12/1000000/real_time | 69007.01 | us | 11 |\n| BM_tbb_mostly_idle/16/1000000/real_time | 94104.69 | us | 7 |\n| BM_dispenso_mostly_idle/48/1000000/real_time | 97169.79 | us | 10 |\n| BM_dispenso_very_idle/1/real_time | 100082.07 | us | 7 |\n| BM_tbb_very_idle/192/real_time | 100087.63 | us | 7 |\n| BM_tbb_very_idle/6/real_time | 100089.99 | us | 7 |\n| BM_tbb_very_idle/16/real_time | 100090.05 | us | 7 |\n| BM_tbb_very_idle/1/real_time | 100090.78 | us | 7 |\n| BM_tbb_very_idle/2/real_time | 100092.04 | us | 7 |\n| BM_tbb_very_idle/3/real_time | 100092.44 | us | 7 |\n| BM_tbb_very_idle/64/real_time | 100093.44 | us | 7 |\n| BM_tbb_very_idle/32/real_time | 100093.52 | us | 7 |\n| BM_tbb_very_idle/8/real_time | 100094.75 | us | 7 |\n| BM_tbb_very_idle/12/real_time | 100095.13 | us | 7 |\n| BM_tbb_very_idle/128/real_time | 100096.93 | us | 7 |\n| BM_tbb_very_idle/4/real_time | 100097.08 | us | 7 |\n| BM_tbb_very_idle/48/real_time | 100097.30 | us | 7 |\n| BM_tbb_very_idle/96/real_time | 100097.92 | us | 7 |\n| BM_tbb_very_idle/24/real_time | 100098.70 | us | 7 |\n| BM_dispenso_very_idle/2/real_time | 100212.54 | us | 7 |\n| BM_dispenso_very_idle/3/real_time | 100244.96 | us | 7 |\n| BM_dispenso_very_idle/4/real_time | 100254.14 | us | 7 |\n| BM_dispenso_very_idle/6/real_time | 100541.71 | us | 7 |\n| BM_dispenso_very_idle/8/real_time | 100772.52 | us | 7 |\n| BM_dispenso_very_idle/12/real_time | 100987.16 | us | 7 |\n| BM_dispenso_very_idle/16/real_time | 101009.44 | us | 7 |\n| BM_dispenso_very_idle/24/real_time | 101734.64 | us | 7 |\n| BM_dispenso_very_idle/32/real_time | 102316.60 | us | 7 |\n| BM_dispenso_very_idle/48/real_time | 103003.23 | us | 7 |\n| BM_dispenso_very_idle/64/real_time | 103934.82 | us | 7 |\n| BM_dispenso_very_idle/96/real_time | 105552.21 | us | 7 |\n| BM_dispenso_very_idle/128/real_time | 107498.07 | us | 7 |\n| BM_dispenso_very_idle/192/real_time | 110912.72 | us | 6 |\n| BM_dispenso_mostly_idle/96/1000000/real_time | 154291.95 | us | 10 |\n| BM_tbb_mostly_idle/24/1000000/real_time | 189093.47 | us | 3 |\n| BM_dispenso_mostly_idle/64/1000000/real_time | 229924.78 | us | 10 |\n| BM_tbb_mostly_idle/32/1000000/real_time | 246954.29 | us | 3 |\n| BM_dispenso_mostly_idle/192/1000000/real_time | 330263.24 | us | 10 |\n| BM_tbb_mostly_idle/48/1000000/real_time | 378955.09 | us | 2 |\n| BM_tbb_mostly_idle/64/1000000/real_time | 479935.20 | us | 2 |\n| BM_dispenso_mostly_idle/128/1000000/real_time | 572013.68 | us | 10 |\n| BM_tbb_mostly_idle/96/1000000/real_time | 760290.44 | us | 1 |\n| BM_tbb_mostly_idle/128/1000000/real_time | 1012521.57 | us | 1 |\n| BM_tbb_mostly_idle/192/1000000/real_time | 1202134.41 | us | 1 |\n"
  },
  {
    "path": "docs/benchmarks/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Dispenso Benchmark Results</title>\n<script src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>\n<style>\n:root {\n  --bg-primary: #0d1117; --bg-secondary: #161b22; --bg-tertiary: #21262d;\n  --bg-card: #1c2128; --text-primary: #e6edf3; --text-secondary: #8b949e;\n  --text-muted: #6e7681; --border: #30363d; --accent: #2ecc71;\n  --accent-hover: #27ae60; --accent-dim: rgba(46,204,113,0.15);\n  --shadow: rgba(0,0,0,0.3); --nav-width: 240px; --header-height: 56px;\n}\nhtml[data-theme=\"light\"] {\n  --bg-primary: #ffffff; --bg-secondary: #f6f8fa; --bg-tertiary: #eaeef2;\n  --bg-card: #ffffff; --text-primary: #1f2328; --text-secondary: #656d76;\n  --text-muted: #8b949e; --border: #d0d7de; --accent: #1a7f37;\n  --accent-hover: #116329; --accent-dim: rgba(26,127,55,0.1);\n  --shadow: rgba(31,35,40,0.12);\n}\n* { margin:0; padding:0; box-sizing:border-box; }\nbody { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; background: var(--bg-primary); color: var(--text-primary); line-height: 1.5; }\n.header { position:fixed; top:0; left:0; right:0; height:var(--header-height); background:var(--bg-secondary); border-bottom:1px solid var(--border); display:flex; align-items:center; padding:0 20px; z-index:100; }\n.header-logo { display:flex; align-items:center; gap:10px; font-size:18px; font-weight:600; }\n.header-logo .icon { width:28px; height:28px; background:var(--accent); border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:15px; color:#fff; font-weight:700; }\n.header-right { margin-left:auto; display:flex; align-items:center; gap:12px; }\n.btn { background:var(--bg-tertiary); border:1px solid var(--border); color:var(--text-secondary); padding:5px 12px; border-radius:6px; cursor:pointer; font-size:13px; transition:all .2s; }\n.btn:hover { color:var(--text-primary); border-color:var(--accent); }\n.btn.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); font-weight:500; }\n.platform-select { background:var(--bg-tertiary); border:1px solid var(--border); color:var(--text-primary); padding:5px 12px; border-radius:6px; font-size:13px; cursor:pointer; }\n.platform-select option { background:var(--bg-secondary); color:var(--text-primary); }\n.sidebar { position:fixed; top:var(--header-height); left:0; bottom:0; width:var(--nav-width); background:var(--bg-secondary); border-right:1px solid var(--border); overflow-y:auto; padding:12px 0; z-index:50; scrollbar-width:thin; scrollbar-color:var(--border) transparent; }\n.search-box { margin:0 14px 12px; }\n.search-input { width:100%; padding:6px 10px; background:var(--bg-tertiary); border:1px solid var(--border); border-radius:6px; color:var(--text-primary); font-size:12px; outline:none; }\n.search-input:focus { border-color:var(--accent); }\n.search-input::placeholder { color:var(--text-muted); }\n.nav-section-title { padding:6px 14px; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:.5px; color:var(--text-muted); }\n.nav-link { display:block; padding:5px 14px; color:var(--text-secondary); text-decoration:none; font-size:13px; transition:all .15s; border-left:3px solid transparent; }\n.nav-link:hover { color:var(--text-primary); background:var(--bg-tertiary); }\n.nav-link.active { color:var(--accent); background:var(--accent-dim); border-left-color:var(--accent); font-weight:500; }\n.main { margin-left:var(--nav-width); margin-top:var(--header-height); padding:24px; max-width:1400px; }\n.info-cards { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px,1fr)); gap:12px; margin-bottom:24px; }\n.info-card { background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:14px; transition:border-color .2s; }\n.info-card:hover { border-color:var(--accent); }\n.info-card .label { font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:.5px; color:var(--text-muted); margin-bottom:4px; }\n.info-card .value { font-size:16px; font-weight:600; }\n.info-card .detail { font-size:12px; color:var(--text-secondary); margin-top:2px; }\n.stats-bar { display:flex; gap:20px; margin-bottom:24px; padding:12px 16px; background:var(--bg-card); border:1px solid var(--border); border-radius:10px; font-size:13px; }\n.stat-item { display:flex; align-items:center; gap:6px; }\n.stat-dot { width:7px; height:7px; border-radius:50%; }\n.stat-dot.ok { background:#2ecc71; } .stat-dot.info { background:#3498db; }\n.benchmark-section { margin-bottom:40px; scroll-margin-top:calc(var(--header-height) + 20px); }\n.section-title { font-size:20px; font-weight:600; margin-bottom:16px; padding-bottom:8px; border-bottom:1px solid var(--border); }\n.chart-container { background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:12px; margin-bottom:12px; transition:border-color .2s; }\n.chart-container:hover { border-color:var(--accent); box-shadow:0 2px 8px var(--shadow); }\n.chart { width:100%; min-height:400px; }\n.chart .modebar { left: 0 !important; right: auto !important; }\n@media (max-width:768px) { .sidebar { display:none; } .main { margin-left:0; } }\n::-webkit-scrollbar { width:6px; } ::-webkit-scrollbar-track { background:transparent; }\n::-webkit-scrollbar-thumb { background:var(--border); border-radius:3px; }\n</style>\n</head>\n<body>\n\n<header class=\"header\">\n  <div class=\"header-logo\"><div class=\"icon\">D</div><span>Dispenso Benchmarks</span></div>\n  <div class=\"header-right\">\n    <select class=\"platform-select\" id=\"platformSelect\" onchange=\"switchPlatform(this.value)\"></select>\n    <button class=\"btn\" onclick=\"toggleTheme()\" id=\"themeBtn\">Light</button>\n  </div>\n</header>\n\n<nav class=\"sidebar\">\n  <div class=\"search-box\"><input type=\"text\" class=\"search-input\" placeholder=\"Filter...\" oninput=\"filterNav(this.value)\"></div>\n  <div class=\"nav-section-title\">Benchmark Suites</div>\n  <a href=\"#section-cascading_parallel_for\" class=\"nav-link\" data-suite=\"cascading_parallel_for\">Cascading Parallel For</a>\n<a href=\"#section-concurrent_vector\" class=\"nav-link\" data-suite=\"concurrent_vector\">Concurrent Vector</a>\n<a href=\"#section-for_each\" class=\"nav-link\" data-suite=\"for_each\">For Each</a>\n<a href=\"#section-for_latency\" class=\"nav-link\" data-suite=\"for_latency\">For Latency</a>\n<a href=\"#section-future\" class=\"nav-link\" data-suite=\"future\">Future</a>\n<a href=\"#section-graph\" class=\"nav-link\" data-suite=\"graph\">Graph</a>\n<a href=\"#section-graph_scene\" class=\"nav-link\" data-suite=\"graph_scene\">Graph Scene</a>\n<a href=\"#section-idle_pool\" class=\"nav-link\" data-suite=\"idle_pool\">Idle Pool</a>\n<a href=\"#section-locality\" class=\"nav-link\" data-suite=\"locality\">Locality</a>\n<a href=\"#section-nested_for\" class=\"nav-link\" data-suite=\"nested_for\">Nested For</a>\n<a href=\"#section-nested_pool\" class=\"nav-link\" data-suite=\"nested_pool\">Nested Pool</a>\n<a href=\"#section-once_function\" class=\"nav-link\" data-suite=\"once_function\">Once Function</a>\n<a href=\"#section-pipeline\" class=\"nav-link\" data-suite=\"pipeline\">Pipeline</a>\n<a href=\"#section-pool_allocator\" class=\"nav-link\" data-suite=\"pool_allocator\">Pool Allocator</a>\n<a href=\"#section-rw_lock\" class=\"nav-link\" data-suite=\"rw_lock\">Rw Lock</a>\n<a href=\"#section-simple_for\" class=\"nav-link\" data-suite=\"simple_for\">Simple For</a>\n<a href=\"#section-simple_pool\" class=\"nav-link\" data-suite=\"simple_pool\">Simple Pool</a>\n<a href=\"#section-small_buffer\" class=\"nav-link\" data-suite=\"small_buffer\">Small Buffer</a>\n<a href=\"#section-summing_for\" class=\"nav-link\" data-suite=\"summing_for\">Summing For</a>\n<a href=\"#section-timed_task\" class=\"nav-link\" data-suite=\"timed_task\">Timed Task</a>\n<a href=\"#section-trivial_compute\" class=\"nav-link\" data-suite=\"trivial_compute\">Trivial Compute</a>\n<a href=\"#section-small_buffer_shared\" class=\"nav-link\" data-suite=\"small_buffer_shared\">Small Buffer Shared</a>\n</nav>\n\n<main class=\"main\">\n  <div class=\"info-cards\" id=\"infoCards\"></div>\n  <div class=\"stats-bar\" id=\"statsBar\"></div>\n  <div id=\"chartSections\"></div>\n</main>\n\n<script>\nconst PLATFORMS = [{\"id\": \"linux-threadripper-192c\", \"label\": \"AMD Ryzen Threadripper PRO 7995WX 96-Cores (192 cores)\", \"machine\": {\"timestamp\": \"2026-03-20T07:38:08.196941\", \"platform\": \"Linux\", \"platform_release\": \"6.19.6-100.fc42.x86_64\", \"platform_version\": \"#1 SMP PREEMPT_DYNAMIC Fri Mar  6 17:40:09 UTC 2026\", \"architecture\": \"x86_64\", \"processor\": \"\", \"python_version\": \"3.13.12\", \"cpu_model\": \"AMD Ryzen Threadripper PRO 7995WX 96-Cores\", \"cpu_cores\": 192, \"cache_size\": \"1024 KB\", \"memory_kb\": 263042332, \"memory_gb\": 250.9, \"platform_id\": \"linux-threadripper-192c\", \"compiler\": {\"compiler_path\": \"/usr/bin/c++\", \"build_type\": \"Release\", \"cxx_standard\": \"20\", \"compiler_id\": \"GNU\", \"compiler_version\": \"15.2.1\", \"compiler_summary\": \"GNU 15.2.1 Release C++20\"}}, \"charts\": [{\"id\": \"cascading_parallel_for_default\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For\", \"traces\": [{\"name\": \"serial\", \"x\": [1000, 100000, 10000000], \"y\": [1433.2252991299833, 150639.50850288518, 27316695.9742447], \"color\": \"#95a5a6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_1000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 1K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1597.6526786908753, 1595.858442974583, 1639.88987622159, 1606.382994328294, 1617.622812578432, 1595.2067424726015, 1610.6311025143316, 1620.081878863651, 1599.3818494617303, 1579.6567483116764, 1583.2650767543917, 1603.1236496781287, 1606.8433902293584, 1654.8264481226076, 1608.7302561440433], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1520.4995647436147, 1587.6488299109042, 1562.2868869101796, 1563.2679377723327, 1571.8059568422946, 1589.0819248360149, 1577.5689309645477, 1561.6740854247107, 1572.0296312435535, 1504.2616602293667, 1563.806343441008, 1559.0777526470263, 1580.6408682791498, 1524.481064226941, 1588.7388651041745], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [7433.991339623322, 16078.47437231796, 23430.244214023274, 24824.41254587218, 19421.428259172004, 24581.34914679514, 28608.203102913663, 32783.370219977776, 46944.24080683258, 59198.092111410944, 81956.91969797487, 106424.7751547934, 155061.25812069332, 213324.40847163877, 33721610.09327225], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [198933.64094199566, 181178.50977872394, 155757.8387740387, 152056.84276448246, 121280.88654681788, 127904.46490569755, 125607.84682226961, 115169.55459628168, 109557.46671139008, 118259.59770990373, 110183.69376962693, 111173.58717502355, 112956.20182903424, 117958.73329843409, 128183.382154162], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [213915.5627250637, 192088.05638498813, 175063.17725305242, 156806.49143186837, 137540.0302279798, 122403.1308253494, 104886.61170257218, 93160.11399237876, 76754.90141547972, 66536.04051422417, 56761.01577104626, 51041.092578332966, 46629.690433035066, 46020.03693160622, 47066.06885716968], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_100000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 100K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [152420.8559519597, 110566.14128587516, 139427.52661387512, 114324.97441649658, 122549.50223636653, 248321.68449647722, 212355.34019759845, 166573.28223583536, 147103.93585910206, 133182.93788038037, 131096.2630668655, 147299.6465052916, 194120.95353327875, 238309.15041857274, 559008.5814474692], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [155806.0507019226, 344469.0263342876, 80005.01594118224, 79085.78889543329, 57769.40553521435, 126800.94548960723, 140472.3950024435, 122526.22979598024, 106495.47675679946, 91151.52776202282, 88426.68602711258, 109635.16350378637, 150894.23119802756, 204875.0882977993, 376090.02265629283], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [159872.02155234266, 98067.4684004659, 80454.20059407095, 67144.6689469462, 55964.44222031628, 47969.931303731566, 44616.355894388995, 49247.61445053098, 61094.715520726924, 72138.56118349626, 93263.0810432683, 116915.38601236366, 171853.34684347536, 222402.01414646962, 56014082.13107405], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1026516.0654023791, 957365.4870926494, 1102143.7508089882, 988306.6601000979, 893393.1580934178, 915672.8841105184, 776217.5186342198, 705531.3538866563, 573279.3550034877, 489268.2841565021, 394535.05191070074, 336112.338380494, 293141.49450994027, 279125.51657129393, 296684.4456628568], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1071773.291415081, 781596.7480508754, 632527.2947928604, 522530.69828471803, 583324.8871063414, 588184.2676244666, 450804.47435245645, 380071.9295229231, 313979.94934118807, 264042.1072059679, 203398.59173080805, 174370.6011202199, 150160.3081067576, 143185.85713128824, 165620.78308088367], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_10000000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 10M Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [27044821.9201838, 23818691.519554704, 21320658.69002065, 22802100.98793167, 22022598.94501377, 19669715.201623052, 16044864.386926886, 15773170.130560175, 13811662.143047947, 13959985.89855264, 14979659.433010966, 15190604.343111595, 14973404.627083473, 15242423.189338299, 16100644.620601086], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [26952636.24036064, 40439965.76906349, 23737628.49985236, 22643515.63838621, 19997795.55388717, 17447722.88016975, 13471732.165955102, 11587558.85465747, 10471183.114568703, 10778084.486339461, 12134331.22029528, 13636197.925370652, 13122847.446917284, 13663618.960294453, 15046445.830957964], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [28141241.971752606, 23961592.211363543, 19775310.862062518, 20505360.14023237, 19671868.66910197, 9831742.032127844, 12212767.611632941, 10737530.344737355, 6821168.2674968075, 5388358.449697067, 3336718.295362185, 2724961.519743854, 2214681.2216285826, 2213046.312721268, 56947737.388933696], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [33081485.634633843, 23783631.68043383, 21404492.000779398, 17684118.26853436, 16629882.771925136, 15109424.199908972, 12930820.862258896, 11461749.349931074, 10711736.66515252, 10623305.763211653, 11888728.280432478, 13802826.54701761, 13644273.156857714, 15178413.239773365, 17276990.24239414], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [32811250.940743666, 24840233.605192583, 23003428.25290404, 20658376.589455627, 16284406.253854271, 16121470.65867303, 13186186.484138792, 11967703.426961562, 12018358.325742686, 10882708.165585436, 11134406.44139489, 12386022.635595605, 13169826.072197497, 14150836.063960854, 16822532.53995441], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"concurrent_vector_serial\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Serial/Access Operations\", \"categories\": [\"push back serial\", \"push back serial reserve\", \"iterate\", \"iterate reverse\", \"lower bound\", \"index\", \"random\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [2766462.8017946407, 223203.1628181616, 110669.9320345043, 107676.25464416042, 26521525.519628882, 108173.62181808498, 803848.9932213981], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [551471.3684873842, 0, 410258.408121762, 397184.4517098201, 35525346.1166285, 642129.8376002585, 1579802.078478492], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [4442104.092392627, 4571737.30703448, 641485.3257807029, 477181.0640233518, 34023883.50150432, 535368.4716536328, 1248877.8229209713], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [5819354.911074444, 1895297.0268256455, 332545.37928740017, 440458.46819967986, 37957291.983886905, 576431.0519265378, 1447134.739747958], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"concurrent_vector_parallel\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Parallel Operations\", \"categories\": [\"parallel\", \"parallel reserve\", \"parallel clear\", \"parallel grow by 10\", \"parallel grow by 100\", \"parallel grow by max\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [130854719.29105765, 127547476.60882357, 121309710.7764851, 33937473.810972676, 14662358.529760892, 6523151.980814574], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [137590424.1165913, 0, 139075949.38063994, 48044665.42678866, 18396568.97040501, 5782772.299933007], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [35857174.60828955, 36634093.21223188, 36209473.991148435, 5986262.531518902, 1851996.9759508967, 638700.5620856725], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [42354153.33487953, 20481351.95260069, 20661971.972209737, 2491046.171772348, 303953.9488707109, 70178.59761575396], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"for_each_1000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1K Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [504.1451565406422, 776.1207873219112, 813.9299861373033, 906.9246215452739, 1213.149196869415, 1491.4937167165792, 3198.479040811303, 3944.953562403192, 5288.227189100151, 7021.325825289052, 9814.161644778034, 12589.963699656302, 19302.748364242198, 27146.68666760577, 52255.37526613838], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1386.855807290837, 3641.7574130289217, 4108.569416704429, 4606.53279316108, 5205.444437046043, 6122.559341145662, 7741.884137158194, 9316.01166410268, 11401.281321257931, 13557.487687704679, 16982.930465857924, 21488.37703942905, 27163.692871145602, 34351.81184225907, 60665.23698735639], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [3171.3590820214054, 6103.33547714431, 6815.720500013154, 7595.940763970903, 8344.007434630143, 9400.140711449747, 11093.938753262242, 11691.362344246225, 13274.637421139334, 14953.140193234138, 16952.032916209282, 19074.137483038514, 22254.52252049462, 26730.257272017025, 61655.226285947356], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1196.9445597559518, 2198.8438946339147, 2527.68118657745, 2664.1779714657087, 2930.5785356735632, 3497.870373176733, 4710.616894304418, 5396.115012094816, 6471.084411088349, 7653.727108285104, 10449.629419136583, 13398.762604364425, 19365.62028482073, 24608.7401998643, 54713.62043483473], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_1000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [499676.7336804722, 254567.7460576101, 171683.6246793721, 134198.74024236796, 91573.577828548, 73578.0301553282, 51622.27599603409, 48382.789924323144, 47700.51891840983, 42158.06311678808, 40873.119955248076, 37939.86049661772, 40546.231674874114, 44040.33404056522, 74040.2906710615], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1585976.955021833, 3476038.7747415476, 3726545.8236892186, 3797711.5057245917, 4120211.8203029847, 4276171.606775261, 4621482.46913707, 4750895.320795446, 5262994.740156037, 5344901.337424383, 5361636.694655509, 5548144.477419555, 5985087.490276262, 8301171.513730771, 10954535.130319225], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [3263128.5914636035, 10622687.987525137, 10085783.621474387, 10070881.947709119, 10675387.1456802, 12962231.507671403, 11936113.489546666, 12070036.420941744, 14066570.138289446, 14206274.214515148, 14649974.77465189, 13690328.503550172, 14761054.18059624, 16547708.57104185, 17139018.46770845], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1260.2231408018342, 2095.8539969954236, 2348.9970027813993, 2576.933211569972, 3082.9263410781014, 3889.0391462683524, 4926.839427716214, 5405.769002244411, 6555.443706214966, 7791.740018662105, 10605.03160251244, 13642.709132193484, 21116.743286699104, 28050.257882473034, 54034.11351733718], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_100000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 100M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [51538677.27968582, 25965838.741948023, 18707137.439472213, 16631091.10901132, 11993987.88210172, 11844514.466722868, 9716727.94125466, 7416418.489888629, 6219252.204904571, 5572207.650251764, 5483320.050844497, 5541364.97074232, 5747581.026467447, 5954843.682683702, 6479821.017191206], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [158208208.45412806, 368762707.1381679, 376320401.49765086, 378984489.8041338, 375148260.0113377, 379307672.8004962, 458390798.39643085, 481957544.782199, 509265998.727642, 503674935.22935545, 523600320.5063753, 531398056.24959993, 588600624.7601472, 621148942.3488578, 886804518.988356], \"color\": \"#e67e22\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_latency_default\", \"suite\": \"for_latency\", \"type\": \"line\", \"title\": \"For Latency\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [35161656.000004224, 33066793.859688915, 32234470.861462448, 31997484.652410176, 31623890.941420488, 31500270.955069963, 31135224.764618803, 31046610.366662636, 30891745.573813643, 30853800.4550535, 30805116.38237273, 30628888.51512552, 30629594.57234041, 30545800.691470504, 31041808.147325784], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [35829096.43039878, 33519619.12947797, 32357082.969079223, 32067964.604886416, 31509286.83339082, 31543902.67228513, 31239965.07287409, 31150412.51465514, 30959615.33836089, 30795198.20611869, 30632024.706231758, 30620872.19030432, 30568353.231132463, 31178996.030410584, 35274160.516062945], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [35330940.03401949, 33347624.032983497, 32374076.726916954, 32054679.605855864, 31470874.726602975, 31162876.806068998, 31032934.164586686, 30855700.08774726, 30791949.780370273, 30859108.535113975, 30647002.867601044, 30711009.46407819, 30738687.3242007, 30692516.735357728, 30671944.119282722], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"future\", \"suite\": \"future\", \"type\": \"grouped_bar_v\", \"title\": \"Future/Async Tree Build Benchmark\", \"categories\": [\"Small\", \"Medium\", \"Large\"], \"groups\": [{\"name\": \"serial\", \"values\": [315383.3762683775, 2624199.9649778637, 20683777.34394744], \"color\": \"#95a5a6\"}, {\"name\": \"std::async\", \"values\": [173624270.70038393, 1546067071.0308478, 20324441333.99986], \"color\": \"#e74c3c\"}, {\"name\": \"folly::Future\", \"values\": [1881214.0792421822, 10418999.524634922, 73082731.51886232], \"color\": \"#e67e22\"}, {\"name\": \"dispenso::Future\", \"values\": [891101.7743970414, 3709310.3518395238, 22619541.362183843], \"color\": \"#3498db\"}, {\"name\": \"dispenso::TaskSet\", \"values\": [382508.1317577007, 1925946.0830548103, 12806701.222827366], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso::TaskSet (bulk)\", \"values\": [315058.768383802, 1882936.0279714626, 12628674.385816712], \"color\": \"#1e8449\"}, {\"name\": \"dispenso::when_all\", \"values\": [1218033.8709797652, 4577371.980005925, 28287060.726242624], \"color\": \"#9b59b6\"}], \"yaxis_unit\": \"ns\", \"xaxis\": \"Tree Size\"}, {\"id\": \"graph_bar\", \"suite\": \"graph\", \"type\": \"bar_h_colored\", \"title\": \"Graph Benchmark\", \"items\": [{\"name\": \"taskflow build big tree\", \"time_ns\": 3003573.408952664, \"color\": \"#f39c12\"}, {\"name\": \"build big tree (Graph)\", \"time_ns\": 1525105.680974031, \"color\": \"#2ecc71\"}, {\"name\": \"build big tree (BiProp)\", \"time_ns\": 1541630.6205106026, \"color\": \"#27ae60\"}, {\"name\": \"build bi prop dependency chain\", \"time_ns\": 45528.82212239234, \"color\": \"#2ecc71\"}, {\"name\": \"build bi prop dependency group\", \"time_ns\": 463.87087945716155, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (Graph)\", \"time_ns\": 19602.78458372719, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (BiProp)\", \"time_ns\": 18466.922687013728, \"color\": \"#27ae60\"}, {\"name\": \"execute dependency chain (Graph)\", \"time_ns\": 7736.775617154331, \"color\": \"#2ecc71\"}, {\"name\": \"execute dependency chain (BiProp)\", \"time_ns\": 7873.851180787661, \"color\": \"#27ae60\"}, {\"name\": \"forward propagator node (Graph)\", \"time_ns\": 1384985.9745220384, \"color\": \"#2ecc71\"}, {\"name\": \"forward propagator node (BiProp)\", \"time_ns\": 1420770.4933902258, \"color\": \"#27ae60\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"graph_scene_bar\", \"suite\": \"graph_scene\", \"type\": \"bar_h_colored\", \"title\": \"Graph Scene Benchmark\", \"items\": [{\"name\": \"scene graph parallel for\", \"time_ns\": 13178492.165113822, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph taskflow\", \"time_ns\": 11724416.132912867, \"color\": \"#f39c12\"}, {\"name\": \"scene graph concurrent task set\", \"time_ns\": 11504798.613304457, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph partial revaluation\", \"time_ns\": 374316.1036985847, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_default\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool\", \"traces\": [{\"name\": \"dispenso_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [100106.0947088436, 100085.70019133567, 100091.04443070966, 100086.6897603763, 100092.01014015291, 100092.20519125284, 100089.49257566461, 100092.7007102984, 100091.80133541425, 100088.27214395361, 100087.2773306799, 100087.9612429777, 100087.1757610834, 100089.2536193576, 100087.49195618466], \"color\": \"#76d7c4\"}, {\"name\": \"tbb_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [100084.50980586487, 100099.73704637516, 100088.5654717595, 100091.66628809735, 100092.53005098019, 100091.31337782102, 100092.768003898, 100090.79504691597, 100091.8422415409, 100093.89442746484, 100093.6893313857, 100096.92804444404, 100095.84642968894, 100096.95523573707, 100098.73604645864], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [6.090463844541889, 6.661289544623591, 4.612891171194431, 6.577072088322926, 12.8352910872034, 330.0981250610117, 438.05853693393635, 491.5541718654308, 474.3194309281403, 477.40821692028214, 471.12525384860305, 412.81347313079755, 399.09782761893234, 407.35327768259464, 502.5944144630782], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [24.1410683527769, 26.70804280757446, 29.046221756246997, 28.256679524107906, 30.801611762979128, 33.88700060717647, 55.993939556153705, 53.50397882457161, 86.09150414229958, 115.306525610755, 266.19544332110905, 444.0785125732271, 740.871004210762, 1013.5170813942352, 1564.6192073498407], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_10000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [21.286698937246648, 21.071808995184323, 24.70661612022917, 26.2714674918092, 32.37181714234788, 3071.5768562537182, 4629.588424305576, 4736.116423068204, 4723.002237338826, 4882.209928459566, 4800.202263841713, 4452.238417600832, 3980.2945027773026, 4116.552756319891, 5079.684369733821], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [237.24057652690655, 253.05716482169402, 261.4750776451775, 281.04991658276157, 336.2862033615493, 393.467231966217, 703.1549575823215, 1022.7745809198034, 2040.8301871416104, 2476.697644063582, 3656.5529715917105, 4945.5835292032925, 7870.291996183023, 10680.594606387762, 15888.419471281979], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1800.194836299925, 1804.6367125764132, 1825.4806751608323, 1841.0117675124384, 1999.8306516199946, 27330.306269844077, 454410.11800430715, 484685.65923394635, 510501.09625793993, 518575.38876356557, 477148.31298799254, 353284.20421574265, 394612.78920061886, 424057.16499779373, 508110.6572470162], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [24993.739764918977, 25686.179948910976, 27120.01293155088, 27634.592146462048, 32100.157101906963, 37571.71964950925, 71298.95682114044, 97146.88304600051, 191379.4213323854, 253836.3761268556, 379963.83500285447, 492460.22501029074, 800471.5946735814, 1073014.4805274904, 1533121.9850340858], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_100000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 100K Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [567718.7187480456, 261377.23079859265, 338593.3023187205, 435125.38425296237, 737377.609976842], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [539907.091952216, 271509.64724545006, 344468.83403013006, 227994.07928970255, 303918.0292229564], \"color\": \"#1e8449\"}, {\"name\": \"omp\", \"x\": [1, 4, 16, 64, 128], \"y\": [534361.3310804078, 157284.85754507312, 78043.87620448327, 133447.4162711926, 239162.16897872597], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [1439896.1380494114, 1210384.0480525761, 843992.7275303366, 414450.3189527502, 348640.0967992654], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_4000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 4M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [21319798.693982694, 16379193.09338093, 9331350.288492136, 6106910.429066788, 6293437.967542559], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [21814113.86086976, 16498608.54890636, 12999220.683080394, 7029749.196566021, 5443119.798974175], \"color\": \"#1e8449\"}, {\"name\": \"omp\", \"x\": [1, 4, 16, 64, 128], \"y\": [21772791.061444763, 5690581.259042235, 1669702.3227393134, 668435.1734407442, 774372.5856306447], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [24177972.943024624, 17294070.61954581, 8296017.341472836, 5445941.191362573, 5159468.507318867], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_32000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 32M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [175459722.83308706, 103129494.2674178, 78476420.64526942, 94186897.07483819, 87019019.08032596], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [174024473.74964443, 95830952.2386463, 71422076.30289097, 77103628.03431806, 92233525.54545271], \"color\": \"#1e8449\"}, {\"name\": \"omp\", \"x\": [1, 4, 16, 64, 128], \"y\": [170459606.1608754, 84148783.33591062, 36167961.78372958, 14011402.531132963, 8495982.679905314], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [177064761.9171844, 94932420.31682959, 98954595.3925699, 75029463.62850101, 88977990.62348592], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_10\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 10 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [5645.801767273857, 6697.275165019456, 5983.401576301956, 6998.933579828141, 6540.57636146004, 6968.777296394821, 7975.769465747315, 8719.130757662515, 10554.474747581737, 11676.441936318217, 14135.132480326874, 15441.503034977191, 18540.012713421227, 21810.51120573949, 25836.53621835947], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [19408.487602948073, 11423.086859705572, 9464.396425552022, 7570.0686352147, 6083.302649153736, 6959.21636301693, 5547.880920465606, 5903.693436083754, 7632.124705790503, 8676.900001221455, 11111.674568554647, 13896.118680423899, 20729.13288186201, 26988.242179455585, 6148427.24352449], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [19470.774580758323, 19643.441179284862, 18177.80331889066, 18168.583875764067, 17755.20170621908, 18918.508599713245, 18175.45897724895, 23111.17534125832, 22989.976317575827, 22029.969426948035, 21122.337256548155, 20395.713909219947, 20607.481436736864, 21075.78443250709, 19042.94967516595], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 500 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [18295488.722570654, 8085964.57161593, 5169146.091818681, 3861745.4284945684, 2542616.7619621586, 1939755.0587883552, 1311536.6354712376, 999137.3410347536, 671964.2329232227, 526180.1937020954, 393245.21192331583, 336656.9168881396, 320564.0410013469, 336909.80793298763, 452809.2592759239], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [20174591.529957324, 8591356.78214555, 5604914.588308552, 4188166.375374466, 2712720.43831338, 2003284.9732587254, 1354354.0701427981, 1036697.7502444471, 709656.8052750267, 565566.1230445926, 418497.83774902567, 344651.2053292274, 402554.89128871966, 305481.05291028117, 6285173.4604037395], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [41392151.51210212, 18216181.196115702, 12018517.332828857, 8689673.16038826, 5781770.771932661, 4302322.209795729, 2903532.70683455, 2264895.6060804655, 1526680.2910718448, 1240413.203374997, 937898.8904792177, 817992.5327060057, 715947.8044910138, 654133.9045039918, 659635.0532023926], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_2500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 2K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1981087186.0245242, 1003708317.4684085, 672672699.0115519, 540238059.7370211, 357161863.00851405, 266615783.9952835, 177660888.66240656, 130403514.3693909, 84379928.54063244, 61954179.84417872, 40962830.912839204, 31796743.073586926, 24255071.84751849, 21095823.79139815, 22355171.75080638], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [2043693608.9536176, 1033487958.542537, 681079891.6655282, 519270054.99601364, 348933480.1561199, 263683738.87089548, 172630516.99652958, 128004181.18422386, 83264280.08149378, 61299957.289931275, 41006460.20120217, 32448058.111455154, 24436597.174128003, 18836969.500245135, 28821591.787026122], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [2353253543.0276766, 1171220326.0394745, 792243187.3545672, 594754630.496027, 402011654.59584445, 304998180.71257323, 202880749.19953942, 150309982.99614742, 98249732.62203415, 73168117.2306148, 49999158.36991644, 38545125.50121096, 28274182.681112535, 22709016.02643885, 17846946.6856482], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_1000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [561.5110823938907, 214.23315263771275, 266.32617216633525, 220.0736441399808, 255.39535468784047, 263.3105888587341, 491.48015493474156, 598.8224601639656, 786.0636636665971, 790.5374640437561, 1788.9931041003697, 1804.3723900336772, 2200.3241039857157, 2604.70770052296, 2675.0122259692844], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [111.65777588218461, 167.29135051716378, 140.260770585813, 142.4424644339689, 109.83408441116131, 95.79625733689345, 169.36375357610396, 141.54544873133185, 156.68389508393648, 191.29878418280006, 195.9300837288661, 175.70291053655444, 192.37952730383515, 215.78623763888757, 291.9531694563973], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [11609.584820852224, 14861.299618231978, 23260.45064136195, 19918.908203445666, 17536.250349432932, 13647.330984895234, 11475.700142035068, 8879.341666276256, 6995.249191162402, 6090.916638364478, 5238.977497375292, 4849.148360768058, 4463.851098543066, 4331.044172339862, 4351.2304969639945], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [816.5969390066623, 690.2990704983843, 650.1700796941151, 563.4425673823984, 494.03058602355117, 474.48593218175637, 503.51715811876863, 518.6600220013653, 591.3495094414734, 652.7099505994678, 672.6824690077553, 1296.9894108132005, 1741.5401244594393, 2125.0747842950086, 2384.798213001132], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_10000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [13906.27705875565, 3288.549179557985, 5577.736401860842, 6430.39589175149, 5439.549300315553, 5445.129815728825, 5246.521314456354, 6409.3522638928125, 9556.114627245688, 9727.944937670449, 19832.651170436293, 16602.82329775076, 24029.753790781288, 26208.495115861297, 28785.290499516308], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [3359.2989660739418, 2588.6582824136144, 2538.561227099438, 3228.1607765859612, 1825.1060094109757, 2622.078020813155, 2022.2084334415717, 1378.006859163598, 1703.3984296055562, 1627.6237450020922, 1908.9737624431145, 1910.2322587902408, 1694.7716843503902, 1027.0844538047604, 1993.8776229803518], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [450063.94078955054, 515094.5247441996, 329381.84160739183, 273963.1469982366, 290061.0505769561, 310126.4443685068, 279716.8006654829, 231524.91728043449, 198706.03650342673, 169625.51966814013, 141459.9449975261, 128411.01668891497, 118215.85717067744, 112419.9654747683, 106952.27314718068], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [25720.881506582195, 26220.078737242147, 26083.382851168237, 25945.654617519016, 25043.08612085879, 26753.065182355705, 26708.70054383538, 24913.667264977943, 20331.206776708073, 17217.193951648547, 13423.523183126807, 11273.055570200086, 9151.145182651184, 17573.208654271988, 25658.422440756112], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_300000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 300K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [2173924.262984656, 169642.42554439063, 319893.1255028583, 580504.3373644972, 556944.4946401442, 754006.3100168481, 547277.9212577734, 481394.80319805443, 341403.3738275369, 263397.59925031103, 345024.1790075476, 484914.2519989982, 691314.4426653162, 782094.419002533, 634940.2366516491], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [553279.7162595671, 185155.28640709817, 190434.54029597342, 211162.30763833632, 186047.321905128, 191267.06270035356, 143009.98845674956, 127544.1037655315, 82652.85904607957, 53943.43257955227, 49439.21600116065, 57706.742242255525, 41295.12085055467, 54539.696852926434, 56159.7689998169], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [4135870.0200216845, 3886821.4320391417, 3583077.8679810464, 3283223.564038053, 2774208.709015511, 2289450.000040233, 1759098.3270201832, 1458545.8665387705, 1067574.971995782, 854228.7249583751, 623412.1776651591, 499684.2445107177, 397035.62180511653, 356765.10849346715, 629828.5257362295], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"skipped_libs\": [{\"name\": \"folly\", \"color\": \"#9b59b6\"}]}, {\"id\": \"once_function_move\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Move Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Once Function\", \"values\": [18.200115813128075, 12.675758420414196, 12.52188034427126, 32.45897671057875], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [90.22610574064771, 98.04443936580248, 94.82982284240283, 103.33237633815814], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"once_function_queue\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Queue Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Inline Function\", \"values\": [1027.143109470045, 1804.8427053006515, 3035.8301109637937, 8985.298515959676], \"color\": \"#3498db\"}, {\"name\": \"Once Function\", \"values\": [2801.8524209845837, 2971.3241144936474, 3446.682486087839, 6576.404779099659], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [3361.821626088938, 3543.9121156492406, 4914.103515310017, 6987.662335701662], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pipeline_bar\", \"suite\": \"pipeline\", \"type\": \"bar_h_colored\", \"title\": \"Pipeline Benchmark\", \"items\": [{\"name\": \"serial\", \"time_ns\": 187840995.17771128, \"color\": \"#95a5a6\"}, {\"name\": \"dispenso\", \"time_ns\": 119103590.2269909, \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"time_ns\": 166112452.5940977, \"color\": \"#3498db\"}, {\"name\": \"taskflow\", \"time_ns\": 120492782.23147506, \"color\": \"#f39c12\"}, {\"name\": \"dispenso par\", \"time_ns\": 4583813.634157973, \"color\": \"#2ecc71\"}, {\"name\": \"tbb par\", \"time_ns\": 4369178.378701578, \"color\": \"#3498db\"}, {\"name\": \"taskflow par\", \"time_ns\": 67558199.37825435, \"color\": \"#f39c12\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pool_allocator_1t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - Single-threaded\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [2975919.9347204734, 14348658.203839716, 13254944.664593901, 57140856.40549357, 17332000.604402572, 76420053.44628003], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [41829.69655771653, 168008.74613465345, 35292.99994628807, 143401.5512679625, 37197.92132828996, 166955.776410512], \"color\": \"#2ecc71\"}, {\"name\": \"Arena\", \"values\": [22772.6631609868, 91573.88395439883, 24500.514847263847, 93817.99278311372, 24446.957975564914, 93475.17965490145], \"color\": \"#27ae60\"}, {\"name\": \"NoLock\", \"values\": [33794.848673860324, 127849.54264510277, 30056.156463357773, 123024.96302838938, 32402.068932969254, 129539.98187919], \"color\": \"#3498db\"}, {\"name\": \"NoLock Arena\", \"values\": [19129.843871014305, 76020.71056192703, 18869.79938539505, 77850.0221602829, 18986.34414661028, 79856.03349275241], \"color\": \"#2980b9\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_2t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 2 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [3282233.900150833, 15278250.93480583, 14093878.28913934, 55199268.77847562, 18578763.810219243, 104357349.50006008], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [160791.86840215698, 577326.7867842158, 179931.52002981378, 584039.71492299, 142368.2185179389, 584453.8737662578], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_8t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 8 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [4166962.9999356717, 17835011.796520676, 15078477.054885298, 54511617.81705818, 45885539.51078549, 396402581.49787164], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [3337312.323306818, 18312848.72508453, 4539657.997843248, 19361157.389700085, 4387526.597263111, 19438887.744611345], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_16t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 16 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [4450289.575121194, 19171191.3692557, 16726744.26772287, 56956960.973833255, 95670608.75027286, 875061692.4953647], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [33040409.303688698, 141298952.00200665, 31212321.33707963, 135157251.50500658, 34722476.0013793, 174422600.78516686], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"rw_lock_serial\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Serial Operations\", \"categories\": [\"2 iterations\", \"8 iterations\", \"32 iterations\", \"128 iterations\", \"512 iterations\"], \"groups\": [{\"name\": \"NopMutex\", \"values\": [302898.2279790129, 321741.76084413845, 339963.1092224516, 305530.71656198817, 234241.11761073474], \"color\": \"#95a5a6\"}, {\"name\": \"std::shared_mutex\", \"values\": [6986149.140999297, 5735710.994366066, 5424167.795307027, 5476145.517391463, 5357427.603941037], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3485600.331573394, 3487103.6946639144, 3487332.4675634885, 3493424.1557493806, 3463243.933589156], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_2\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (2 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [6879518.196227187, 71866493.78854781, 167318594.00169924, 341148277.99688405, 677657012.323228, 1352303583.9898512], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3700086.488429688, 28392350.266221914, 133017257.26729879, 508057433.99541825, 2760446025.9899497, 9022123825.037851], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_8\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (8 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [5951811.882392383, 115266769.44534606, 341040573.9975561, 580087924.337325, 1217093817.0165756, 2481908222.078346], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3720033.916284554, 29537342.013266515, 112291602.57713182, 349326075.1944035, 1204738817.526959, 3991187106.0030537], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_32\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (32 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [5439939.5951844305, 108378071.25062683, 310903409.8451957, 887331245.0014054, 2087598671.0889266, 4436426979.955286], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3664471.061734883, 20912511.30629217, 60963214.51266042, 187014475.99839106, 591411885.6502076, 1940640599.001199], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_128\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (128 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [5272600.472741068, 70298664.95513883, 213834074.64335588, 482531272.3405659, 1080140528.5019426, 2182503418.0656075], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3696541.874298611, 15678133.679560976, 43702080.71676366, 106150809.05048862, 293041637.001027, 877953816.4963014], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_512\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (512 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [5083712.509668401, 31957196.472730074, 81975506.10984088, 220818660.00209832, 447109856.759198, 836072857.3364515], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3729210.1123302164, 14379766.992969465, 34453917.16668382, 80204004.19831276, 194945967.50009805, 482794601.6099304], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"simple_for_1000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [145.1576499406187, 145.1576499406187], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [149.61118094670408, 149.38001612164715, 150.43078616512554, 151.0383588350627, 150.83205236033433, 148.25166694870714, 150.48665518043407, 153.07804303421852, 151.92769032502483, 148.35583111169882, 151.38875431015967, 154.5471518311366, 150.09538709677673, 150.75179215093763, 153.91277685815493], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [832.4648379903613, 1467.2887715688491, 1500.7217809578617, 1486.78320627105, 1453.226355112451, 2514.4078403804365, 3067.598129856155, 4235.101146729439, 6169.035169282156, 7451.089281800264, 9674.570891217429, 12519.62525619168, 17646.232039260907, 22076.28717305528, 6428535.765823894], \"color\": \"#e74c3c\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1012502.0308070816, 2433231.9090104173, 1499217.7407440073, 1119299.945966871, 1743259.860735679, 1997683.1636576657, 1858385.4431876317, 1910188.8538672186, 1917513.1979669419, 1860444.2379753995, 1855939.16174477, 1852478.6908898107, 1842383.985786944, 1640110.6900302693, 2155663.8299953192], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [24540.274503863173, 22354.358596126964, 19562.374220622096, 18559.42437674245, 22904.185512123266, 25243.202453151276, 24579.77229056028, 23452.26192820792, 21603.611224089917, 19768.60924613651, 18541.838145521946, 17531.90774049164, 18040.79448454231, 19161.111234444616, 20270.132624257603], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_1000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [148426.6688174368, 148426.6688174368], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [144541.080940483, 96730.55577956568, 67619.90766465041, 52457.446046075864, 37147.996018067875, 31959.86605036914, 38171.69459803292, 41170.93334540972, 44117.384477506435, 43176.80709504921, 42286.29317292531, 35061.372302416894, 35672.71995283248, 38213.318484197625, 53955.16301712985], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [144641.39494751344, 75915.22145009942, 54520.801253825324, 41325.43440433061, 29213.35921850156, 23412.237352729913, 18878.962594416003, 14503.1855097176, 12623.428493121623, 12976.136910789395, 13527.269325258048, 15592.475089923177, 21633.21891987572, 26753.703492930174, 6562273.815523844], \"color\": \"#e74c3c\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [21314442.99618784, 23181538.255820867, 21663585.795572232, 14317329.590872785, 10737052.410280725, 12690871.465061385, 17279020.178112622, 18369660.877757274, 19351821.975902084, 17373276.05939674, 17069242.209306415, 15856202.943027977, 15108879.653453689, 14598880.534839906, 14576062.559348542], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [253236.9001590969, 197961.7395780509, 161119.6313296689, 141510.67542643435, 116589.32333639829, 101413.52143324054, 83226.05312479338, 76789.65544027885, 67870.22136416154, 63140.80217511872, 56813.61349479082, 53719.74151370136, 52710.297401243944, 54255.577049793785, 64402.872752429794], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_100000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [24937919.827015508, 24937919.827015508], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [20892851.117441393, 17081643.027606707, 13725195.16851753, 12465606.128367094, 8303066.8511263905, 9663655.05716697, 6277820.284239857, 6293089.594298697, 5955852.953168991, 5780447.599326455, 5358049.182177638, 5901207.768618031, 5717746.178619564, 5848543.381431649, 5903559.317249023], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [21714866.09244757, 18675493.4838973, 17438571.0351839, 17913056.248072706, 18064284.79962051, 14478039.413890136, 11060544.579037229, 8013386.695310768, 6325738.405951509, 5001837.920657277, 3769977.1153991325, 3296111.5179396556, 2911125.159463867, 2978487.211087172, 8407626.247817539], \"color\": \"#e74c3c\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [200012609.49842012, 258498884.56539938, 185123988.1652873, 213046969.000802, 221819641.17626196, 264321961.3553009, 247957636.84740064, 258675649.36979085, 203259672.52481344, 201954033.2270977, 187184466.54384023, 202122975.23837712, 204517530.77806032, 205455565.29247886, 214881837.64959726], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [21923932.193407826, 18580971.660558134, 16370165.366419123, 9905376.84491097, 10035532.352048904, 7996179.568398671, 6385689.838170316, 6566035.839387626, 5841974.912108491, 5866863.586915992, 6575457.51457413, 5912406.162281897, 4983235.089904161, 6060687.081788428, 8473697.67013374], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_pool_1000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [16.521736001990295, 3.437250282336804, 82.48202245936636, 238.60889164150169, 285.6565791735474, 268.86470386473655, 552.7195157316912, 561.1728238562625, 221.64628649524582, 423.68281675906275, 299.9373104178571, 399.2788882930379, 497.9731720494199, 398.63692219246866, 383.21899944513603], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1.0502425700769027, 4.99290260076885, 27.21966166059483, 43.97671725141422, 59.30666154066613, 102.16786168843696, 170.2692574937828, 150.92567923334659, 159.41165712003786, 151.59976234750712, 98.11694822662457, 153.45995248742386, 150.18007841386384, 167.11171290584016, 196.02369462225914], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [269.13754211025355, 278.93653556157113, 354.4661606418155, 427.1909511806206, 511.76684523187345, 486.5229397578868, 452.887560073743, 518.2549154730121, 618.1528434791727, 448.00666232677287, 446.5722677606166, 478.3706501179086, 490.44937359003376, 532.9109185854693, 700.3198381488686], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [24.927065692179184, 26.329147187883446, 26.45929264204295, 27.446563866006528, 28.70057424631941, 36.240268633413855, 72.30507148525898, 51.466464692080464, 175.06843337193786, 152.23555614609532, 377.8091076774951, 636.4516592730467, 857.7263606193807, 1437.8365998815975, 1145.5587564585767], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_10000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [132.30819975826626, 28.237171047271204, 486.3578481246338, 2529.4653509684335, 2136.004001390442, 2514.671435690812, 3018.0796752811398, 2930.253258963035, 3561.7206038092054, 4842.360783987773, 5285.769109614193, 4803.573193163028, 4896.998193872802, 5149.824611798484, 3664.4027757913223], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [10.109557947339345, 44.73185133896239, 291.9235122402643, 471.6253898995781, 615.5942675366334, 937.1221643346474, 1758.5095409303904, 1626.2682075865534, 1552.580257092919, 1370.9539501107079, 1478.9639762377371, 1550.3636120403087, 1556.784197132807, 1647.0284830530197, 1587.5697459450553], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [2010.886523173893, 3757.041840811088, 4844.02545258568, 3914.6886010411818, 4235.994653532458, 4649.032283854741, 4609.0470812547965, 6889.265382189019, 5035.754096146168, 5895.224203914917, 6285.655474347466, 6649.934910819866, 5771.14592886321, 5785.03550829651, 7144.154317431011], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [263.31877018242494, 274.82677019028876, 287.0116065640696, 285.86862528836144, 306.7960046341345, 373.3840963834914, 515.0495367681879, 671.9443664342681, 1834.2539200093597, 3276.850437456166, 4719.372044130338, 5592.753475145718, 7139.984721348423, 8655.248829296117, 11522.855125013333], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_1000000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [13481.202903979769, 2947.1443183198735, 56462.300982309025, 188927.95814567112, 214237.81900666654, 353281.404163378, 366008.5449926555, 279008.6681322594, 363004.38226317056, 438891.9136021286, 356638.30938283354, 365818.34838725626, 384193.06848663837, 381785.8848293933, 354469.02667172253], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [987.4532030416054, 3870.3117051413183, 35303.08223773979, 48173.12866604576, 43775.44354938436, 161228.20807728343, 157661.44500006564, 155586.16061193438, 156651.09656817678, 159689.32940158993, 153666.270386356, 158513.41172121465, 151935.3028968908, 154440.88949256443, 148155.81942509327], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [215967.3314438098, 276269.13983840495, 395009.3394960277, 405391.7092678603, 446125.33778417856, 477376.88475172035, 476656.07373346575, 560906.1277646106, 617663.1397393066, 570848.9939958478, 505241.53766067076, 662707.637733547, 630678.9189887544, 649783.1986829018, 694757.3783497015], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [33897.193129647705, 34631.4642377103, 35223.01955993082, 37308.14375408125, 40078.42890806151, 42137.80499897742, 63213.63420883084, 80289.49611784461, 168674.38628936984, 314954.0234257334, 477441.73000101, 582578.1119929161, 808698.0386869982, 927672.6834941655, 1129510.3834709153], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"small_buffer\", \"suite\": \"small_buffer\", \"type\": \"bar_h_colored\", \"title\": \"Small Buffer Allocator Benchmark\", \"items\": [{\"name\": \"newdelete[S]/8192\", \"time_ns\": 78683.88066652126, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192\", \"time_ns\": 156759.58997214196, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/8192/threads:16\", \"time_ns\": 98552.20900080343, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192/threads:16\", \"time_ns\": 195985.78937062365, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768\", \"time_ns\": 330888.496627741, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768\", \"time_ns\": 523717.6264852773, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768/threads:16\", \"time_ns\": 389286.9101982354, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768/threads:16\", \"time_ns\": 791073.308781571, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192\", \"time_ns\": 430077.6971718124, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192\", \"time_ns\": 112376.09196133995, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192/threads:16\", \"time_ns\": 580271.5925448057, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192/threads:16\", \"time_ns\": 237714.8166023336, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768\", \"time_ns\": 2048902.4556949376, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768\", \"time_ns\": 450040.82409814774, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768/threads:16\", \"time_ns\": 2952121.4191018688, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768/threads:16\", \"time_ns\": 906217.6969988892, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192\", \"time_ns\": 782766.3094818211, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192\", \"time_ns\": 112184.39382140143, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192/threads:16\", \"time_ns\": 1186305.3205161123, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192/threads:16\", \"time_ns\": 267911.83978168515, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768\", \"time_ns\": 3539301.873118765, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768\", \"time_ns\": 452319.70194350433, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768/threads:16\", \"time_ns\": 5523193.665873765, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768/threads:16\", \"time_ns\": 998855.2242768964, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"legend\": [{\"name\": \"SmallBufferAllocator\", \"color\": \"#2ecc71\"}, {\"name\": \"new/delete\", \"color\": \"#e74c3c\"}]}, {\"id\": \"summing_for_1000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [289.6005293875894, 289.6005293875894], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [312.2187094366394, 316.2979850203427, 312.40136814247387, 316.03588292738596, 311.8125822602392, 311.85363496150075, 324.74961020347183, 321.6150838391804, 314.4518922239314, 308.71024421408447, 326.7222974446451, 325.99103796257043, 334.79385580396104, 319.0686862685745, 334.6174949512944], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [972.5855519491528, 1488.2550375757246, 1483.3221227119222, 1460.9917857122746, 1682.8524329387374, 2503.0318058038574, 3108.55554205422, 3647.8771381501806, 5588.595004288755, 7122.483113705193, 10840.87867387822, 13560.40772585706, 19682.850388074192, 25526.95345062251, 717489.4180901389], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [27029.055686918076, 26593.643220746264, 25053.67035010068, 23320.072440003114, 21669.686142609415, 21566.44191108164, 20710.9944401379, 19528.43827800899, 20387.033166619127, 19180.09585213517, 17874.46314575948, 18881.773659865397, 18063.29994631622, 18636.519660151513, 15784.488232148879], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_1000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [290511.27474489785, 290511.27474489785], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [294829.5416378372, 180554.71034606482, 135066.36860658586, 106998.65823651476, 76694.65946188818, 59949.48197379607, 42594.567229894885, 33992.32441036033, 33515.36892970289, 36247.07310039107, 35984.82354913241, 39487.31287752315, 45378.84737672402, 45672.658782108876, 65357.42835082342], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [288138.7433443224, 149156.19580228065, 101538.11962328898, 80622.18058496845, 54114.126451600634, 41697.85632194792, 29361.131554399675, 24350.770617411286, 19143.750215746404, 17171.635391448555, 16241.456883889328, 17921.592996339787, 24163.647369464117, 30706.337758464862, 6100074.037831449], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [403493.5163035475, 281568.274920703, 226901.44324902346, 189875.47055606495, 147836.1768384963, 121350.21547791566, 96203.81804214139, 79544.09240476412, 63400.96816572183, 54578.12200274297, 44730.19666766904, 40597.999420023945, 39416.406270257234, 39647.8976723195, 31362.84491624082], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_100000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [29084164.53442753, 29084164.53442753], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [30539515.722517133, 17494623.040681187, 12720908.21879635, 9493494.662128285, 6979325.340785254, 5389377.613682497, 3741997.2607515273, 3177839.2187480438, 1971023.717116408, 1642503.5226647654, 1485629.6122166845, 1475880.765779452, 1484003.024248099, 1520769.213689185, 1796906.472967689], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [29233748.60481897, 15074987.069237975, 10761478.990155024, 8034382.125060801, 5883168.166867276, 5461308.927827537, 3949553.076222184, 3545358.6006352725, 2087736.1857679843, 1566006.9020447708, 1199778.177374245, 971301.5522323807, 999687.132860343, 775406.6091334885, 6689136.420634816], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [30426905.39801055, 15246663.978489647, 11014413.101560801, 9347527.619883304, 7781236.132190146, 4976691.158107875, 4627876.291065769, 3230722.2953954907, 1954722.5791987784, 1923923.2937901383, 1510703.3289669002, 1445601.7815099622, 1473428.5733698613, 1470118.0987582076, 1550643.7367082636], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"timed_task\", \"suite\": \"timed_task\", \"type\": \"grouped_bar_h_error\", \"title\": \"Timed Task - Scheduling Jitter\", \"categories\": [\"2ms (Normal)\", \"2ms (Steady)\", \"4ms (Normal)\", \"4ms (Steady)\", \"6ms (Normal)\", \"6ms (Steady)\", \"Mixed (Normal)\", \"Mixed (Steady)\"], \"groups\": [{\"name\": \"dispenso\", \"values\": [27.140469872392675, 33.15717534035652, 27.048115013167187, 35.652824022868316, 34.79623445309686, 21.994207497414084, 5.729239188755512, 13.25252736439585], \"errors\": [39.26980323384966, 44.912856182945696, 31.390342298115364, 20.879758342796617, 48.66726682928979, 19.398465095117334, 5.81856081671094, 31.67401925688938], \"color\": \"#2ecc71\"}, {\"name\": \"folly\", \"values\": [95.06486796773933, 93.6233249886268, 96.95655324961982, 93.66584334868824, 112.35004855785579, 78.75578021719309, 65.1959498863039, 59.60014752544842], \"errors\": [141.78820903420984, 57.420382483699015, 270.12745352402544, 6.205024556313576, 411.4314817090677, 30.58280796108715, 197.75921061042865, 3.9182525955013396], \"color\": \"#9b59b6\"}], \"xaxis_label\": \"Mean Scheduling Error (us)\"}, {\"id\": \"trivial_compute_100\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1350.67698304802, 1376.2797238766152, 1405.6027138750324, 1411.29718495238, 1379.7596765673707, 1364.417215676475, 1376.6631367391433, 1356.6830931164197, 1400.5808996084356, 1375.2972452727515, 1358.0364768211948, 1489.0797786133835, 1509.090866917206, 1442.3813020266336, 1551.350254099816], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [2090.2514677630497, 2142.0910936523483, 2235.182444719835, 1921.9938130546711, 2187.5988356598546, 2685.5481395255333, 3253.1471155468093, 4338.474365387438, 6456.13749719944, 7778.469836066934, 10413.30787204524, 13430.334520099297, 19702.18571359484, 26262.325690816368, 6148972.6933130305], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [8696.457077940235, 9725.35110363063, 10349.578688842974, 10422.62069369878, 11400.623008853066, 12341.240041609353, 13488.799352548083, 15118.654041821126, 16057.454124670176, 16331.867219594173, 16659.770673448176, 16829.03621358427, 17800.632064203106, 18587.926018693677, 15276.640580268577], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_1000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [51863849.75648962, 51863849.75648962], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [52309520.02429625, 25377341.58353747, 17288701.50832189, 12858173.644250156, 8666508.236447835, 6623211.646546559, 4426180.934914206, 3309469.7488249633, 2254618.149348048, 1715786.9304059078, 1288945.7159792213, 1154805.4747543826, 1016670.1793926472, 1028019.4289966971, 1019556.6713891589], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [49584102.14333396, 42985081.08108856, 28435189.70864049, 21895593.45349631, 14841395.59241677, 11266212.746173747, 7575781.794602645, 5653712.32614363, 3786611.1127126543, 2840537.340957621, 2011657.779440748, 1558994.9003856333, 1215047.6416775505, 1001926.9168988806, 6245890.788971569], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [49410317.42491759, 25674075.201442022, 17174998.41939688, 13252048.701863527, 8928044.167226452, 6789485.354637426, 4546968.570663927, 3428122.7447293736, 2388410.036200889, 1803849.158026208, 1271657.4115311783, 1033947.1428803285, 790595.2599505514, 643282.8781693627, 571341.3915533718], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_100000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 192], \"y\": [1399299244.4545963, 1399299244.4545963], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1375330757.5243526, 714575235.3438487, 489631742.5009329, 369329597.1606858, 249211537.62261385, 188320188.45502964, 125901212.70349139, 94574359.67950997, 63193635.940975085, 48424842.29646454, 34063354.33734761, 27665412.932013474, 22667969.424470235, 20711409.05294063, 19291527.787263088], \"color\": \"#2ecc71\"}, {\"name\": \"omp\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1415209950.9956315, 726854279.016455, 508420653.0009396, 388268271.39128, 275552845.5018066, 217170940.793585, 157498503.0769872, 128075455.58248152, 97735861.54915394, 82937143.76166463, 70971454.56743117, 64620135.34473954, 59362319.13640061, 55723424.43141482, 58871815.69252991], \"color\": \"#e74c3c\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192], \"y\": [1352936672.9781032, 687719183.3142812, 460955460.4161531, 349988193.5034258, 236514067.44546774, 179268747.91737643, 119136739.16650522, 89829074.17837693, 61243230.12067401, 46501795.10936141, 32990284.24155568, 27317037.134167008, 21736599.171576515, 20283679.438669387, 18457328.223962788], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}]}, {\"id\": \"macos-m4-pro-12c\", \"label\": \"Apple M4 Pro (12 cores)\", \"machine\": {\"timestamp\": \"2026-03-20T10:21:46.312656\", \"platform\": \"Darwin\", \"platform_release\": \"25.3.0\", \"platform_version\": \"Darwin Kernel Version 25.3.0: Wed Jan 28 20:51:28 PST 2026; root:xnu-12377.91.3~2/RELEASE_ARM64_T6041\", \"architecture\": \"arm64\", \"processor\": \"arm\", \"python_version\": \"3.12.13+meta\", \"cpu_model\": \"Apple M4 Pro\", \"cpu_cores\": 12, \"memory_gb\": 48.0, \"platform_id\": \"macos-m4-pro-12c\", \"compiler\": {\"compiler_path\": \"/usr/bin/c++\", \"build_type\": \"Release\", \"cxx_standard\": \"20\", \"compiler_id\": \"AppleClang\", \"compiler_version\": \"17.0.0.17000604\", \"compiler_summary\": \"AppleClang 17.0.0.17000604 Release C++20\"}}, \"charts\": [{\"id\": \"cascading_parallel_for_default\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For\", \"traces\": [{\"name\": \"serial\", \"x\": [1000, 100000, 10000000], \"y\": [700.5002372642518, 82564.75728780165, 10531123.778919743], \"color\": \"#95a5a6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_1000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 1K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [625.2072446734195, 609.6258327131047, 614.8547995581773, 619.0147180562062, 615.6145224666849, 615.83017610162, 616.0202263334468], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [605.3549102323939, 617.2509080811373, 613.3981068106079, 612.0413117420418, 617.5104589566071, 613.3846055813841, 612.7556064463755], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [40468.82442649334, 42482.3762312714, 45956.75770636757, 45833.22422490524, 46524.635821323674, 48438.211717099184, 56151.88080459915], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [46310.25147244597, 36138.46328049984, 31020.54828164434, 29387.4583047368, 26002.083333358834, 28964.18050935298, 25367.38346523467], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_100000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 100K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [85654.28327098917, 42077.09785398746, 45516.625336456906, 28130.824395788124, 51310.06670417264, 69758.33538707634, 74868.07102310973], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [85467.14405634196, 79109.74436570091, 39438.96633034339, 24877.132421022685, 33889.15822521801, 33917.59121880441, 52009.26850175269], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [194204.43730386806, 143290.9542392476, 127191.27097948182, 116269.12205482468, 111341.52506072912, 106468.23834384317, 113265.23871415642], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [191380.60106839883, 119517.87857815709, 104196.9531729645, 86986.97978760907, 69326.33316816197, 63590.45366329318, 61339.696066824254], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_10000000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 10M Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [10497190.92526487, 6129634.956029796, 5701286.0676931115, 4770311.714269053, 4712284.769588184, 4715272.09417932, 5178351.670037955], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [10221724.044126661, 8297997.093651184, 5467769.354361836, 4694495.618184048, 4577143.490160292, 4465798.116589506, 4684942.952613503], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [13662088.23552976, 7987072.793017516, 5930657.608879972, 5149498.361888833, 4815002.013768615, 4719341.271968723, 4786840.799778444], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [13977541.660424324, 8006809.658995322, 5897592.034433847, 5095387.384653145, 4709900.731858391, 4616176.873747728, 4597889.256394027], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"concurrent_vector_serial\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Serial/Access Operations\", \"categories\": [\"push back serial\", \"push back serial reserve\", \"iterate\", \"iterate reverse\", \"lower bound\", \"index\", \"random\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [317631.75918000605, 261712.85686013865, 39443.283205270054, 64897.47868062467, 24293461.204345886, 39254.75478558765, 592005.574148366], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [614917.6790694814, 0, 290307.6555123664, 295664.90570821706, 61653189.371678635, 237289.22645850817, 628493.8764702143], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [1901861.0733125925, 1891775.1136688967, 666610.9269613884, 671254.0748197861, 57641239.58457882, 667483.0545559882, 1280694.1369220752], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [1892992.4542159848, 1833904.557434735, 516669.6923579964, 516030.6968759185, 38295150.44344589, 499907.56601044675, 818150.7488936796], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"concurrent_vector_parallel\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Parallel Operations\", \"categories\": [\"parallel\", \"parallel reserve\", \"parallel clear\", \"parallel grow by 10\", \"parallel grow by 100\", \"parallel grow by max\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [10624761.82375355, 10547246.835548196, 10716977.430598088, 1948020.7374894537, 914227.1580535817, 420329.71342349506], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [11115774.874471955, 0, 11207459.514428463, 2911470.346509676, 1872851.9370237926, 695439.1593492385], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [87730963.00299382, 87510212.99718155, 88056013.89354302, 9460173.790821021, 1857728.3462802845, 1028960.8476811956], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [68354545.45745796, 68953137.50719652, 68515670.45404491, 6772294.874491097, 705237.9522188487, 65862.77835994957], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"for_each_1000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1K Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [55.4285662143635, 209.61013946923532, 497.69985200673796, 797.0115552080647, 1681.6550966608227, 2194.8983982229347, 4148.266248173059], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [1724.050130778557, 3744.823717605097, 4458.698299872223, 5686.056015611495, 11357.86527222049, 13613.211335330809, 21813.72889580406], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [2460.3825501094193, 3443.647309368769, 4992.919059544994, 6003.801196348504, 10456.12934644083, 13214.687562046598, 26436.440189742774], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [852.899485639906, 1260.7515992551105, 1735.8688661636231, 2197.126010211535, 3847.4478202412515, 5052.495694912164, 6499.172459342831], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_1000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [49261.80024954423, 26275.125356732882, 24247.138666426854, 17623.938267413094, 21452.541621925207, 19786.268223890063, 27283.67128917349], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [1743384.40930762, 3713450.2687671734, 5034803.749294952, 5919903.669497767, 12118319.915686497, 16010042.577464549, 51859881.91321182], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [2584803.2406496783, 4416677.815347293, 6871792.702350673, 7257237.797603011, 11571150.278809985, 17512853.126390837, 54945833.30582827], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [877.080617834821, 1333.3816144933303, 1806.667626529415, 2370.3171414366916, 3947.9827332155937, 5488.374464619157, 6589.241517441614], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_100000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 100M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6919777.227132259, 4510779.574423307, 4024521.068045446, 3582819.6610777806, 3481717.9146921267, 3446394.502497255, 3751593.9732250622], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [173638468.7537793, 382169207.9654895, 500838895.9686272, 637812250.0609607, 1427234707.9822793, 1651335333.9396417, 5021056332.974694], \"color\": \"#e67e22\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_latency_default\", \"suite\": \"for_latency\", \"type\": \"line\", \"title\": \"For Latency\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [54589112.15492452, 43784244.40510571, 43358578.46993296, 42765568.58573766, 41872441.172873706, 41280727.943076804, 42843593.75014901], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [48862776.785556756, 35739713.55945104, 43657950.49670851, 42058494.74965362, 40954658.87803584, 42402966.129884586, 41874554.68490952], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"future\", \"suite\": \"future\", \"type\": \"grouped_bar_v\", \"title\": \"Future/Async Tree Build Benchmark\", \"categories\": [\"Small\", \"Medium\", \"Large\"], \"groups\": [{\"name\": \"serial\", \"values\": [219139.01982541961, 1746741.9372347356, 14027711.65827289], \"color\": \"#95a5a6\"}, {\"name\": \"std::async\", \"values\": [354523624.9919981, 31890174.27344383, 254601930.6561599], \"color\": \"#e74c3c\", \"error_indices\": [1, 2]}, {\"name\": \"folly::Future\", \"values\": [4020985.052920878, 31890174.27344383, 254601930.6561599], \"color\": \"#e67e22\"}, {\"name\": \"dispenso::Future\", \"values\": [690767.3022359964, 4652623.606380075, 34612708.300119266], \"color\": \"#3498db\"}, {\"name\": \"dispenso::TaskSet\", \"values\": [577466.0965300396, 4399069.448341973, 34593860.39758101], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso::TaskSet (bulk)\", \"values\": [574602.0913438357, 4764640.664731796, 33979803.573207125], \"color\": \"#1e8449\"}, {\"name\": \"dispenso::when_all\", \"values\": [678018.4960766424, 4746979.870675068, 36242789.472453296], \"color\": \"#9b59b6\"}], \"yaxis_unit\": \"ns\", \"xaxis\": \"Tree Size\"}, {\"id\": \"graph_bar\", \"suite\": \"graph\", \"type\": \"bar_h_colored\", \"title\": \"Graph Benchmark\", \"items\": [{\"name\": \"taskflow build big tree\", \"time_ns\": 2875657.4077010457, \"color\": \"#f39c12\"}, {\"name\": \"build big tree (Graph)\", \"time_ns\": 827747.3067011156, \"color\": \"#2ecc71\"}, {\"name\": \"build big tree (BiProp)\", \"time_ns\": 862210.0879697884, \"color\": \"#27ae60\"}, {\"name\": \"build bi prop dependency chain\", \"time_ns\": 60791.02103590594, \"color\": \"#2ecc71\"}, {\"name\": \"build bi prop dependency group\", \"time_ns\": 541.1421435173419, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (Graph)\", \"time_ns\": 9584.254691533728, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (BiProp)\", \"time_ns\": 10396.300373474847, \"color\": \"#27ae60\"}, {\"name\": \"execute dependency chain (Graph)\", \"time_ns\": 3659.363984078001, \"color\": \"#2ecc71\"}, {\"name\": \"execute dependency chain (BiProp)\", \"time_ns\": 3698.6554966538197, \"color\": \"#27ae60\"}, {\"name\": \"forward propagator node (Graph)\", \"time_ns\": 951695.781049668, \"color\": \"#2ecc71\"}, {\"name\": \"forward propagator node (BiProp)\", \"time_ns\": 990644.596558096, \"color\": \"#27ae60\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"graph_scene_bar\", \"suite\": \"graph_scene\", \"type\": \"bar_h_colored\", \"title\": \"Graph Scene Benchmark\", \"items\": [{\"name\": \"scene graph parallel for\", \"time_ns\": 8991288.89432177, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph taskflow\", \"time_ns\": 5869669.512383895, \"color\": \"#f39c12\"}, {\"name\": \"scene graph concurrent task set\", \"time_ns\": 6132357.387795602, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph partial revaluation\", \"time_ns\": 211265.1030637419, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_default\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool\", \"traces\": [{\"name\": \"dispenso_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [103949.43443991776, 102323.14886525273, 102151.94643075977, 101760.25587134063, 101917.30356642178, 102839.75000493228, 101509.90472175181], \"color\": \"#76d7c4\"}, {\"name\": \"tbb_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [104556.84515181929, 104071.60714800868, 104046.22029247029, 102836.98800152967, 104953.79771704653, 104008.9107118547, 103789.22613537205], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [2.6099716967115327, 2.876337148986388, 4.577939389659891, 6.169086150290484, 33.59804067846777, 120.55436597638365, 99.13712003313648], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [19.876605094076083, 21.382990475001293, 22.286794489143066, 22.525470509770873, 27.53688208799312, 30.76591581644336, 31.450521047075117], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_10000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [10.086900307693051, 9.700433531144588, 19.14006889841207, 23.499718650882027, 47.57320341472196, 541.0529615320906, 456.7189913485089], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [202.49054977371108, 211.45170473564627, 218.94605381951504, 223.13469074011047, 266.5956322427677, 291.8967149035802, 307.4214535463992], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [784.5392460475488, 767.9795059623211, 781.1575677727682, 794.2233294421088, 924.4239060244159, 9090.774577672188, 5547.0087507274], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [20110.643383197705, 21075.44572826362, 21924.488279182697, 22010.22312886292, 27368.96795865435, 28985.84850217131, 27960.51908323231], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_100000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 100K Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [260737.31134979508, 126822.4602494415, 233759.12656686342, 890183.0614990272, 1744616.6465763834], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [256090.7359074651, 133841.48384591582, 110695.41330053339, 162321.85666438678, 287738.9424298849], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [445868.729002541, 205472.97945906932, 173522.08809559952, 173656.44600198994, 173070.272941234], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_4000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 4M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [10334427.074720973, 4752867.173828535, 2846860.394078451, 3673726.0665410226, 4649647.163121519], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [10075088.700146547, 4509631.679423201, 2717709.7443036065, 2859782.0796892936, 2831912.5803297055], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [15213417.587801814, 4108408.823445001, 2564908.771595934, 2547032.087633427, 2570804.0435953685], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_32000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 32M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [87189692.75651035, 38419599.56076203, 23323620.832525194, 24227678.173639137, 25613959.82463312], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [80980611.11134787, 36509410.049276136, 26487858.03898203, 24607481.310497325, 28115873.483733997], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [120765617.99040063, 33021849.24195033, 23729265.7959564, 23557516.66861276, 23197238.90007784], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_10\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 10 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [2479.9473156576137, 1714.804801569383, 1468.1176928052757, 1326.2928186469464, 2478.049009819242, 2678.877158411769, 4652.9743209281805], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [14961.287396672922, 12207.42807181078, 12109.488096784127, 11760.601240849077, 11638.886580109067, 14006.300714716304, 12124.174831781393], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 500 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [5935303.946898784, 3007479.995645025, 2061836.6300057666, 1524610.7034138679, 1016174.1976500363, 776653.9522837027, 841270.4513078536], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [8783293.869591465, 4241980.457057555, 2869621.8084425055, 2134516.5890350845, 1444861.9526096864, 1110844.1524429114, 1001690.9234882687], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_2500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 2K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [583668707.9863622, 294945667.0321524, 212272416.6838452, 188557124.98771027, 113317701.34468873, 80586281.241267, 64663950.00461489], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [453164749.9534302, 243543985.998258, 161323500.01134908, 112321208.39413257, 71781819.45346296, 50853854.17138847, 43659128.00754554], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_1000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [237.19465645511926, 151.14610276406873, 157.7835167379135, 142.0926124703182, 308.4210979784735, 401.3422819099427, 565.7262010323052], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [69.99702763920337, 121.31665213227481, 109.35908843443853, 108.74788342634731, 175.95745601048554, 145.60373717097258, 185.18111481053103], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6308.988814621612, 6073.80393713746, 5519.547379545627, 5577.856549488395, 10230.621324701453, 15092.790765846346, 26041.050924471132], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [677.9331226057667, 542.970623957662, 587.9234428400231, 555.4199165536756, 587.1199152306101, 563.036702108008, 577.751663792432], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_10000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [7160.414123137919, 2193.1773761789486, 2517.0265841314495, 2530.2844020137, 4163.695912900734, 4653.025000090046, 4338.411623938306], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [1895.4101352121781, 1733.7116674752906, 1413.0601574664893, 1257.5391203369848, 1902.5739074677497, 1790.606889443182, 1817.8500427063882], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [228647.87497868142, 199361.65264031538, 176662.8750192467, 179852.5414778851, 333325.68750483915, 512416.7500762269, 881811.0000574961], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [21761.02016106128, 17681.982731673776, 15489.978723208162, 12552.85566107237, 11108.409728022349, 10250.611914255258, 9308.678650113783], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_300000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 300K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [1148256.374988705, 187597.614742117, 196777.96875475906, 209864.9999825284, 281596.97198619443, 356942.9999915883, 444069.0830233507], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [292041.08350677416, 130980.92500586063, 111263.52084102109, 100296.16670882596, 103861.78570999099, 82522.8843346445, 85837.98962354194], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [3296486.375038512, 2090060.2079927921, 1534770.958009176, 1185793.9169276506, 867856.0410626233, 734020.6250082701, 778120.04100997], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"skipped_libs\": [{\"name\": \"folly\", \"color\": \"#9b59b6\"}]}, {\"id\": \"once_function_move\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Move Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Once Function\", \"values\": [5.204623791909096, 6.812845839092673, 7.438441518400829, 27.811982148424182], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [24.158670975557346, 24.550034826692528, 24.582920522600364, 44.21355443294617], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"once_function_queue\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Queue Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Inline Function\", \"values\": [627.0593616821525, 1124.6337175150072, 1817.4631815245443, 7571.629852905779], \"color\": \"#3498db\"}, {\"name\": \"Once Function\", \"values\": [1398.8958840787318, 1539.047102661202, 1890.5727399449413, 10222.249092835804], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [2734.0989397390713, 2964.939429110469, 3246.7841850951504, 10034.847177918622], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pipeline_bar\", \"suite\": \"pipeline\", \"type\": \"bar_h_colored\", \"title\": \"Pipeline Benchmark\", \"items\": [{\"name\": \"serial\", \"time_ns\": 114005916.67431097, \"color\": \"#95a5a6\"}, {\"name\": \"dispenso\", \"time_ns\": 60666458.33197981, \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"time_ns\": 105327486.00235207, \"color\": \"#3498db\"}, {\"name\": \"taskflow\", \"time_ns\": 100358023.85703261, \"color\": \"#f39c12\"}, {\"name\": \"dispenso par\", \"time_ns\": 13244808.961215585, \"color\": \"#2ecc71\"}, {\"name\": \"tbb par\", \"time_ns\": 18570681.720221832, \"color\": \"#3498db\"}, {\"name\": \"taskflow par\", \"time_ns\": 100174589.2821678, \"color\": \"#f39c12\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pool_allocator_1t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - Single-threaded\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [297837.8959717182, 1393100.5615561914, 312082.44089198427, 1286931.7644694145, 3967560.369346757, 15925258.522408761], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [35381.84665267378, 144298.9355109866, 35833.98831308906, 144236.78231143608, 35744.06120115258, 146309.707341323], \"color\": \"#2ecc71\"}, {\"name\": \"Arena\", \"values\": [21265.480894466433, 86182.02232244628, 21059.53734711275, 85263.86002597825, 21021.85662787536, 86704.20746064727], \"color\": \"#27ae60\"}, {\"name\": \"NoLock\", \"values\": [32329.23618875474, 133055.0820002276, 32361.86439259558, 132326.7975434407, 32453.493513815025, 133103.29765478693], \"color\": \"#3498db\"}, {\"name\": \"NoLock Arena\", \"values\": [21064.785143470246, 84566.9069640627, 21147.46064142755, 85567.00244149553, 21179.439691280913, 84837.98606465747], \"color\": \"#2980b9\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_2t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 2 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [1257238.148684627, 5947916.66411891, 1016821.344399603, 1979630.9191059102, 17206997.976910956, 69498659.09039296], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [191077.9184113632, 1017347.9984911489, 193045.1749578554, 1071525.3937138817, 191963.53768421395, 1022619.2788928854], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_8t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 8 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [3733305.555581061, 15166702.127936196, 3693569.2224355917, 15767791.676586743, 98668744.8748853, 387625041.53419286], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [21899995.53541254, 94885845.79667076, 17763089.136375736, 110689090.91409296, 25595886.67936623, 73615657.45021734], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_16t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 16 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [8368770.837058457, 34217269.91402228, 9259785.644503104, 40081666.66608304, 218771116.80805683, 844508291.920647], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [13813426.250126215, 98524399.99813214, 16729679.932309823, 111432819.50110881, 6825904.255396033, 68130451.39036451], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"rw_lock_serial\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Serial Operations\", \"categories\": [\"2 iterations\", \"8 iterations\", \"32 iterations\", \"128 iterations\", \"512 iterations\"], \"groups\": [{\"name\": \"NopMutex\", \"values\": [285183.70649920136, 286609.3173463474, 291821.08153557987, 333605.1836488914, 304676.5871115709], \"color\": \"#95a5a6\"}, {\"name\": \"std::shared_mutex\", \"values\": [10781069.015138201, 10617996.84998043, 10062712.499140095, 9875637.323359473, 9892706.59596918], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3389171.1167050796, 3393791.261093088, 3316036.556772712, 3430593.8475188753, 3324420.814804062], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_2\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (2 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [10857366.030820861, 48073186.1355404, 223555250.01573065, 868961500.0039339], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3584332.2789863814, 29757812.502793968, 153225666.7560432, 1005173167.0973823], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_8\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (8 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [10633065.384955935, 48234949.354082346, 211338639.02650774, 945047250.0175238], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3549493.4747494156, 25392336.44320457, 129610604.16031007, 681908959.0571821], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_32\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (32 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [10262880.435523886, 51817922.64504891, 210097471.98938084, 902531540.9526229], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3500579.1455591517, 19340842.104467906, 93561865.77739815, 421600875.0372566], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_128\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (128 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [10063079.757882016, 64839170.908089735, 201540541.5149871, 769367125.0017359], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3494274.7902823617, 18518503.631323416, 80677546.32793367, 303473750.01292676], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_512\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (512 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [10008825.586243933, 107829791.57686765, 187002697.9886461, 527345874.9288693], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [3497630.653168126, 15670082.399932045, 72606312.49907117, 345658187.5216216], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"simple_for_1000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [3.7497375160455705e-10, 3.7497375160455705e-10], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [46.04082318406511, 46.121137047132294, 45.6716139252072, 45.31050043920065, 45.043442278045454, 44.65237938838554, 45.36657069061462], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [353843.63749762997, 611494.5324984838, 676986.7403423571, 652553.273910907, 673465.8076437403, 669435.7599653136, 640626.19177924], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [8165.779896374998, 8037.026042295156, 8037.461237201799, 8240.657407288209, 8341.751115465577, 8312.600589860573, 6706.632388555734], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_1000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [3.33995558321476e-10, 3.33995558321476e-10], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [53254.1927425466, 29055.281845266134, 25434.214130765933, 20753.614803694283, 21763.29528190336, 19784.576820456372, 30466.086278966693], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6618754.4964528605, 7100949.651334974, 6924421.50928823, 6658505.492121828, 6728089.886210299, 6686934.74677363, 6173689.661123745], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [100227.72385754847, 59484.88355694319, 52727.867978380484, 43392.40593667623, 34315.32071344646, 31916.541818011847, 29117.38528583078], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_100000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [4.159519448876381e-10, 4.159519448876381e-10], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6973216.671030968, 4434089.062851854, 4035585.920331673, 3537435.68695604, 3492578.0762363262, 3488039.7899542004, 3816219.086142918], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [65613551.46935539, 62734740.45696535, 55741849.60810605, 66204095.930727415, 66936078.59249988, 67894904.34245883, 68204006.95072576], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [7338198.684891196, 4650172.735070994, 3990181.3467043787, 3615828.155578534, 3496726.758979336, 3519768.33480876, 3609583.9740039827], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_pool_1000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6.6472640090395885, 53.13554169842973, 115.53375434739398, 176.5114003512969, 336.5354872048485, 366.3849066597106, 367.56199222496895], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [0.7554262456378871, 36.13760710292121, 74.59056004233452, 83.86936523736156, 149.81741747684936, 125.04704669342217, 149.13546308786368], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [148.68277557375256, 170.54736633995935, 182.11511766673323, 261.15918846509015, 307.15302201430643, 335.81870731240946, 311.4121848613852], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [19.8398803228476, 21.453196654229036, 22.69957908730194, 23.50722269228718, 28.096659465626274, 30.80636348632513, 35.63749802625345], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_10000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [65.35277969934586, 791.3980158735757, 1056.4191873696327, 1480.8765901477043, 3175.5945183923122, 3376.355930463184, 4013.4710867946246], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [7.199973038284088, 355.62803120720656, 766.3786014103714, 849.6708571910858, 1335.4970106814542, 1266.95488848222, 1527.3928964851088], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [1534.4369516752888, 1571.235376169972, 1884.3878383955193, 2626.10696147328, 3088.5960000037885, 3101.0480765521957, 3003.0686610742755], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [198.3208854826877, 214.01594311394868, 225.85424600509342, 236.0107824733456, 271.23990176574523, 302.4201432583473, 350.3743648728832], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_1000000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6503.729743524155, 64677.60609335859, 101286.94788727444, 136104.68339174986, 316134.353983216, 353628.5205045715, 384219.5204924792], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [718.8960889369584, 35827.11874623783, 82232.31011329012, 88812.23437492736, 139060.3750187438, 134771.74999813238, 153261.50821056217], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [159814.14599809796, 170841.8227499351, 188804.3542567175, 263194.27764974535, 296969.9170207605, 281913.70848799124, 284064.2704977654], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [118496.85420747846, 71578.05089890544, 48723.08976840801, 34684.518500903825, 31769.51890451495, 38521.57458344376, 39328.79821054245], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"small_buffer\", \"suite\": \"small_buffer\", \"type\": \"bar_h_colored\", \"title\": \"Small Buffer Allocator Benchmark\", \"items\": [{\"name\": \"newdelete[S]/8192\", \"time_ns\": 125303.26364931643, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192\", \"time_ns\": 53302.40831650446, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/8192/threads:16\", \"time_ns\": 314926.0268187123, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192/threads:16\", \"time_ns\": 120258.6493397035, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768\", \"time_ns\": 508444.8953462875, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768\", \"time_ns\": 214782.18355085887, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768/threads:16\", \"time_ns\": 1201311.3235155412, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768/threads:16\", \"time_ns\": 444873.3035522829, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192\", \"time_ns\": 124989.33357486768, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192\", \"time_ns\": 60749.228267215316, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192/threads:16\", \"time_ns\": 429508.1455493346, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192/threads:16\", \"time_ns\": 162576.32181965004, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768\", \"time_ns\": 505341.70981474785, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768\", \"time_ns\": 244387.94149076848, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768/threads:16\", \"time_ns\": 3098163.281538291, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768/threads:16\", \"time_ns\": 678291.8443492603, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192\", \"time_ns\": 138000.96970177098, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192\", \"time_ns\": 57018.46957966995, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192/threads:16\", \"time_ns\": 1934699.7973154932, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192/threads:16\", \"time_ns\": 190252.0963226593, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768\", \"time_ns\": 573576.0461350502, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768\", \"time_ns\": 225975.01609099738, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768/threads:16\", \"time_ns\": 7334677.465093722, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768/threads:16\", \"time_ns\": 757798.5616080696, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"legend\": [{\"name\": \"SmallBufferAllocator\", \"color\": \"#2ecc71\"}, {\"name\": \"new/delete\", \"color\": \"#e74c3c\"}]}, {\"id\": \"summing_for_1000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [61.868015977933, 61.868015977933], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [73.21236872374634, 73.83848047515738, 75.63617836556358, 75.48505532789856, 76.54764035438431, 75.94152857903019, 76.52603958821783], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [8098.8852890526505, 7902.885981032539, 7910.169754879776, 7924.401366363232, 8467.075966689852, 9021.862826939605, 7333.295140880929], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_1000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [62131.92283685184, 62131.92283685184], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [62124.53013849104, 32542.895864285958, 23049.065345463572, 18169.309326149654, 18001.76831836735, 17093.629762444518, 19147.251492042946], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [73253.95878199255, 44695.539841018835, 37628.8799210418, 32160.988931691067, 25780.759752318532, 24416.323301077882, 21390.852327258417], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_100000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [6271191.964125527, 6271191.964125527], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6243269.7231997745, 3192353.977250274, 2180611.7600537953, 1783559.7206169788, 1660651.514533925, 1646918.6396995708, 1661169.339654936], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6311540.910344874, 3253811.628146227, 2251415.4695676635, 1787936.53366924, 1652575.4951761058, 1658270.8342896854, 1616450.6518942937], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"timed_task\", \"suite\": \"timed_task\", \"type\": \"grouped_bar_h_error\", \"title\": \"Timed Task - Scheduling Jitter\", \"categories\": [\"2ms (Normal)\", \"2ms (Steady)\", \"4ms (Normal)\", \"4ms (Steady)\", \"6ms (Normal)\", \"6ms (Steady)\", \"Mixed (Normal)\", \"Mixed (Steady)\"], \"groups\": [{\"name\": \"dispenso\", \"values\": [9.954080702737015, 9.970294406141319, 9.957789792679334, 9.87145451636459, 9.97726479545248, 12.824925219724841, 9.979554878858284, 9.894181556958925], \"errors\": [0.46880110198638036, 0.0479700518865891, 0.35240762570797746, 0.4525810659416707, 0.19193815931339261, 26.843810624597428, 0.04522015442280679, 0.5092770671500604], \"color\": \"#2ecc71\"}, {\"name\": \"folly\", \"values\": [496.583849638699, 556.840214172594, 879.7843848215387, 724.7286991763077, 1326.24398026615, 1082.90358630563, 165.04625329437124, 209.31231811562878], \"errors\": [141.5301833754346, 991.2055774021107, 365.41615103797983, 242.89857675277736, 533.976408747388, 345.7069676219512, 209.45683632331378, 29.049332138882715], \"color\": \"#9b59b6\"}], \"xaxis_label\": \"Mean Scheduling Error (us)\"}, {\"id\": \"trivial_compute_100\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [580.5775178253743, 574.6406038290687, 576.7989511892471, 575.9769562459976, 577.9981914972198, 580.669442029208, 579.405533944817], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [6661.6069209022635, 6561.512048899096, 6409.191173429974, 6319.209270760749, 6044.838730943729, 5689.791837089, 5460.399416127546], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_1000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [21648549.500241645, 21648549.500241645], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [21669511.719665024, 11017505.859854281, 7488596.181266326, 5612743.663601578, 3738881.6845658068, 2882029.6882384038, 2278961.006548996], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [21669519.53040552, 10992401.046678424, 7441054.521861704, 5626434.959069924, 3741124.774434514, 2839112.8048164453, 2344558.6611112384], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_100000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 12], \"y\": [561459167.045541, 561459167.045541], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [562269250.0473931, 292155500.035733, 197789510.4791969, 148385433.3870113, 99080214.29354058, 74509717.54992174, 59913069.41723451], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12], \"y\": [561830165.9123971, 285128250.0196248, 192430114.7519145, 144186466.79259837, 96028398.85545628, 72845012.50833273, 58966774.25092397], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}]}, {\"id\": \"windows-xeon-64c\", \"label\": \"Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz (64 cores)\", \"machine\": {\"timestamp\": \"2026-03-20T08:41:43.239873\", \"platform\": \"Windows\", \"platform_release\": \"11\", \"platform_version\": \"10.0.26100\", \"architecture\": \"AMD64\", \"processor\": \"Intel64 Family 6 Model 85 Stepping 4, GenuineIntel\", \"python_version\": \"3.12.4+meta\", \"build_system\": \"buck\", \"cpu_model\": \"Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz\", \"cpu_cores\": 64, \"platform_id\": \"windows-xeon-64c\", \"buck_mode\": \"@//arvr/mode/win/vs2022/opt\"}, \"charts\": [{\"id\": \"cascading_parallel_for_default\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For\", \"traces\": [{\"name\": \"serial\", \"x\": [1000, 100000, 10000000], \"y\": [18126.627687758595, 1871601.288658641, 220908233.33322382], \"color\": \"#95a5a6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_1000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 1K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [14741.759505814864, 14866.492413625363, 14865.525890659896, 14921.40076993976, 14880.833174482921, 14875.458359071257, 14904.42826552466, 14960.11693150802, 15067.048285931416, 15164.856751282998, 15460.382925693075, 15871.433659830913], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [14243.51815976715, 14454.417251627463, 14459.798994977096, 14461.002768250732, 14487.468247245839, 14981.62688442219, 14597.607545926017, 14578.580021558022, 14678.90569058702, 14820.44156991453, 15077.182680519616, 15202.662605176862], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [877918.8191872248, 414515.7829837441, 386387.0933331782, 355204.88165662787, 314773.19910519477, 273383.04259647196, 251369.3841224314, 218689.1682783568, 207745.9195742041, 209731.00321736166, 229503.06258320724, 246281.44404327663], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [791001.9911504951, 327248.2580038129, 265875.1975417691, 230665.2159576594, 179306.16999503932, 154205.31222896997, 129092.03311861103, 112570.32480305883, 98240.52514576392, 90351.59126779658, 91064.52671654278, 82600.54857143718], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_100000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 100K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1526928.6036036154, 830264.0661934267, 552650.9630814242, 418455.98086170544, 305991.36195059965, 234318.33848856762, 231394.4796063695, 194020.85293197815, 225480.14256624988, 275664.885158758, 299774.4963143794, 371656.00933474954], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1551691.7840362117, 875754.9277272715, 581173.9238408143, 407334.73479957413, 306607.85590283823, 253322.8764805983, 187819.57671968502, 179148.2964603572, 171820.64357765776, 190077.3506493753, 218409.92927868612, 228597.69425139533], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [4912614.788729987, 1933018.4357528584, 1554351.3742066827, 1211951.7793598466, 947158.3446412793, 816632.6508622769, 622457.1186436861, 526803.6189064309, 447190.9441234014, 419638.83323490515, 421511.16475537355, 433133.18777279864], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [5489421.37404694, 1714686.9135799925, 1231472.3776223848, 953330.4347833862, 740634.8499515749, 574660.2098466336, 411137.214484413, 315095.1845182348, 259162.0267261534, 234158.54800928867, 216791.39382621433, 201929.6593186341], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_10000000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 10M Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [199952066.66650724, 102800599.99994202, 68918229.99996294, 51819028.57137694, 40618217.64705254, 29560056.521760367, 23345778.571410846, 22031491.428554416, 20624918.421067137, 19562622.222211856, 17898750.000002015, 19239791.89187604], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [196639033.33336446, 132378919.99997373, 74751255.55558608, 52591566.666706055, 39176384.21051762, 30249945.4545465, 24379596.428583942, 20655768.750003744, 17909888.571427602, 18614663.157892976, 18371323.076910183, 18697297.29728656], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [406839450.00000674, 128752666.66666599, 93706199.99992868, 63308690.909087256, 43474174.999971636, 33269757.142859038, 23640117.24135896, 20076718.181812655, 17050264.99998894, 16541778.571427995, 18093715.384636126, 18486284.210523177], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [387399300.0001974, 128894866.66654193, 83954150.00006779, 66419772.72730318, 42381318.75001727, 32760295.238100905, 23412256.66665802, 20146739.99999234, 17918942.10526535, 17288219.04762732, 17730107.50000594, 17831479.487190686], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"concurrent_vector_serial\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Serial/Access Operations\", \"categories\": [\"push back serial\", \"push back serial reserve\", \"iterate\", \"iterate reverse\", \"lower bound\", \"index\", \"random\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [7517800.892864151, 2753903.787878919, 156543.87429409043, 677335.9821425272, 56842154.545434326, 159802.67616011872, 2473420.714285827], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [29579995.999993116, 0, 1169003.5714293248, 1645808.705356038, 179241824.99996278, 1016580.3212857594, 6518578.571428536], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [14866904.000009527, 15424524.000009114, 1340234.136545675, 2751136.1445778976, 102715500.00000691, 2669900.757575416, 3134037.7118656267], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [13250582.142859457, 13223976.78572023, 673235.602677989, 6679877.678574746, 227708700.00022113, 3376679.3427198986, 3642050.2564093717], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"concurrent_vector_parallel\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Parallel Operations\", \"categories\": [\"parallel\", \"parallel reserve\", \"parallel clear\", \"parallel grow by 10\", \"parallel grow by 100\", \"parallel grow by max\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [328254399.9998779, 324387349.9995971, 329473050.0001606, 56859089.99994353, 21150102.439028937, 3556605.1339291753], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [736798500.0000771, 0, 707295700.0000315, 282806100.00001615, 73043863.41463503, 29776539.99999651], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [58401463.6363215, 58540649.9999408, 60796890.90909762, 12945349.999995414, 4198957.558142062, 1595859.8214293066], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [44388806.66669623, 44234699.99999404, 41515088.235267766, 5652936.607142627, 643807.8000001042, 61743.41964286408], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"for_each_1000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1K Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1084.4699918143858, 1519.7095313950595, 1572.0795541952234, 3625.7103880354125, 5356.712675701717, 5282.134275190921, 7214.105845864306, 9071.630338554369, 12871.75152419334, 18384.761152789448, 23181.046055678067, 28533.958616168267], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [8009.351882652337, 39165.639671349956, 33065.22613718145, 58973.15430992767, 56404.99216112503, 52330.86058374619, 53960.34922351268, 61547.38193015489, 62366.87425594681, 67295.12595833918, 62915.879215068206, 63817.547683906836], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [10174.795394057788, 23197.568309595623, 23822.924668656386, 28461.893775754656, 28092.8603182864, 23696.57033848705, 24074.114119192094, 31412.114670590858, 33222.74918770779, 39872.901301540194, 43408.90551919424, 49250.57859209888], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3307.6101141892304, 6816.580744751944, 6890.116630755298, 8672.007690145374, 6706.4651624836015, 10548.869852954203, 11562.660136162458, 12325.000000005935, 15582.740043637485, 19274.075809962564, 26063.528397031692, 29953.151175792107], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_1000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1034970.1183433633, 595689.3707482524, 405083.57857527357, 1127796.8000003968, 216627.5757576152, 171827.0224171569, 402656.97606550186, 305066.35200955323, 213281.2044373861, 216792.99242427622, 168218.04952229635, 160331.34177218293], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [8026022.988501765, 20114088.57142669, 55972607.69228832, 62716099.99996806, 49736192.8571211, 58105458.333329804, 53120723.07690239, 53590591.66668582, 58538541.66662132, 56744900.00001242, 47827500.00000911, 43286262.50003254], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [17695149.99998339, 31141654.545453176, 30434668.181814313, 29903634.782583497, 44486087.49999039, 34372458.33333691, 32176096.000002872, 41001626.08697049, 36350609.09089754, 33771790.476185694, 32093731.578961045, 33987964.999960236], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3201.5060654608983, 6997.247003823731, 7690.123813500883, 8664.049509344155, 6846.994038311776, 10638.479908910924, 11471.217398130926, 12281.87570834865, 16018.497056011467, 20795.44116044832, 23569.208303997504, 30612.809046745686], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_100000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 100M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [109234616.66667815, 66536019.999966815, 44435031.250031896, 76661340.00000966, 21261312.12119645, 35425519.99998977, 27262089.47368784, 28305817.391296647, 20998077.41935013, 18547441.025638808, 17987158.139539834, 16404246.341463897], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [851916500.0006979, 4051674400.0005927, 4515227100.000629, 4694814299.999962, 4861839099.999997, 5035947000.000306, 5235028399.999464, 5249350699.999923, 5716208199.999528, 6091953799.999828, 4860996599.999453, 4421639799.9998665], \"color\": \"#e67e22\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_latency_default\", \"suite\": \"for_latency\", \"type\": \"line\", \"title\": \"For Latency\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [39721527.77775288, 35242369.99996901, 33481509.523794338, 32807752.380947582, 31958850.000013296, 31791295.454530135, 31275231.818199243, 31198531.818187226, 31174109.09089813, 31008299.999998797, 31082345.454540864, 31251334.782609772], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [47286566.66666211, 47342366.66669555, 47161833.33330264, 47164519.99999359, 45003046.66665518, 38977068.42101462, 33855600.00000017, 31342742.85713175, 32234536.363665197, 31261881.818202462, 31327159.09094424, 31395763.63636562], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"future\", \"suite\": \"future\", \"type\": \"grouped_bar_v\", \"title\": \"Future/Async Tree Build Benchmark\", \"categories\": [\"Small\", \"Medium\", \"Large\"], \"groups\": [{\"name\": \"serial\", \"values\": [2028086.1764711197, 16244425.581410112, 130485699.99991742], \"color\": \"#95a5a6\"}, {\"name\": \"std::async\", \"values\": [26942503.70371231, 227501300.00016117, 1784169900.0000517], \"color\": \"#e74c3c\", \"error_indices\": [0, 1, 2]}, {\"name\": \"folly::Future\", \"values\": [26942503.70371231, 227501300.00016117, 1784169900.0000517], \"color\": \"#e67e22\"}, {\"name\": \"dispenso::Future\", \"values\": [1055777.927928472, 6899076.237621754, 51183699.99998625], \"color\": \"#3498db\"}, {\"name\": \"dispenso::TaskSet\", \"values\": [592249.4097811138, 4015842.8571417714, 31573409.090924546], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso::TaskSet (bulk)\", \"values\": [557404.2959427392, 4001654.0697674933, 32546909.52382502], \"color\": \"#1e8449\"}, {\"name\": \"dispenso::when_all\", \"values\": [1051290.000000068, 6891887.254904063, 51322991.66666598], \"color\": \"#9b59b6\"}], \"yaxis_unit\": \"ns\", \"xaxis\": \"Tree Size\"}, {\"id\": \"graph_bar\", \"suite\": \"graph\", \"type\": \"bar_h_colored\", \"title\": \"Graph Benchmark\", \"items\": [{\"name\": \"taskflow build big tree\", \"time_ns\": 25833532.142866846, \"color\": \"#f39c12\"}, {\"name\": \"build big tree (Graph)\", \"time_ns\": 5941274.999997859, \"color\": \"#2ecc71\"}, {\"name\": \"build big tree (BiProp)\", \"time_ns\": 7067700.892849059, \"color\": \"#27ae60\"}, {\"name\": \"build bi prop dependency chain\", \"time_ns\": 136213.96143027165, \"color\": \"#2ecc71\"}, {\"name\": \"build bi prop dependency group\", \"time_ns\": 2581.249501953236, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (Graph)\", \"time_ns\": 28032.311462890517, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (BiProp)\", \"time_ns\": 28677.725099469477, \"color\": \"#27ae60\"}, {\"name\": \"execute dependency chain (Graph)\", \"time_ns\": 12356.560714286908, \"color\": \"#2ecc71\"}, {\"name\": \"execute dependency chain (BiProp)\", \"time_ns\": 12459.033928572742, \"color\": \"#27ae60\"}, {\"name\": \"forward propagator node (Graph)\", \"time_ns\": 4592369.798608569, \"color\": \"#2ecc71\"}, {\"name\": \"forward propagator node (BiProp)\", \"time_ns\": 4386797.315437556, \"color\": \"#27ae60\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"graph_scene_bar\", \"suite\": \"graph_scene\", \"type\": \"bar_h_colored\", \"title\": \"Graph Scene Benchmark\", \"items\": [{\"name\": \"scene graph parallel for\", \"time_ns\": 28857943.478294108, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph taskflow\", \"time_ns\": 18099464.864856087, \"color\": \"#f39c12\"}, {\"name\": \"scene graph concurrent task set\", \"time_ns\": 11973226.415064791, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph partial revaluation\", \"time_ns\": 601544.1176478347, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_default\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool\", \"traces\": [{\"name\": \"dispenso_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [100577.44285716451, 100477.97142864771, 100540.0285714911, 100614.27142863977, 100561.41428568869, 100445.54285715484, 100716.21428583706, 100619.41428570468, 100809.07142855723, 100698.04285714262, 100645.08571420966, 100877.25714285106], \"color\": \"#76d7c4\"}, {\"name\": \"tbb_very_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [109419.05000011805, 109621.98333330282, 110211.93333332728, 110327.7166666885, 110105.26666662675, 110184.99999993634, 110196.56666667288, 109524.91666663869, 110043.38333335302, 109811.11666660581, 110293.11666667734, 110031.40000002533], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [8.091717308393113, 7.865715993701925, 7.062882083147959, 23.93396188851053, 739.6942999994279, 612.7190036897774, 1178.2056034480224, 1309.8851926987982, 1296.4471193411969, 1196.9085365851752, 1688.3561797755071, 1514.9509761400375], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [108.8943249964334, 69.1143796305345, 82.3244678334926, 85.62411599828017, 67.20751362197133, 69.92567730279316, 104.24887310905096, 106.03587738499377, 156.75190960457957, 187.40803738333446, 363.61430715384876, 503.2907000004343], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_10000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [36.18218463303709, 36.99201541547904, 39.99319278492162, 40.5917188667003, 739.9537000001146, 7024.2270000017015, 12050.136956521903, 13561.712765952874, 13500.390384618953, 14603.163461533068, 14461.65434781901, 15286.295652181847], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1000.6933333323826, 620.2325531908269, 636.8153915394709, 673.0084057965098, 668.5194202899753, 714.8282807727232, 969.1446969697214, 945.3789473677593, 1489.867413442556, 2000.9383522728347, 3367.8325471684284, 4465.587591242509], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3199.7547945205097, 3199.5041284379677, 3391.3839449536295, 3227.848623854188, 4759.788292686586, 62171.90172413932, 1307685.699999638, 1238735.9000003925, 1438651.7000002642, 1432174.6999994502, 1476455.6000000085, 1503446.4999998817], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [97064.52857140642, 60487.027272674, 81091.33333336003, 67081.8818181777, 66798.31111109201, 81787.74444442954, 88620.65000005258, 126471.58333326539, 140749.56000004022, 179141.89999987686, 342533.0000000031, 473776.59999983734], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_100000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 100K Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [1372865.0099412487, 396449.9296767358, 287872.9962547995, 691375.1780263986, 1333293.4823094946], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [1398130.0403227785, 640431.7915690942, 257724.575617164, 394259.36990761163, 655733.5664337942], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [4713486.754969339, 1118057.2799989022, 509874.96136003983, 513410.16949110146, 509839.9423218571], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_4000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 4M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [68272969.99999817, 17701070.73171835, 7704507.21649899, 6780490.00000101, 7062852.222225046], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [66101881.81821286, 17390972.500015777, 7736593.975907058, 7678023.655918428, 6323190.816323292], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [103735385.71418197, 20089636.842098307, 6958756.122448718, 6393008.411221196, 6524390.476191738], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_32000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 32M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [559581600.0004561, 174945149.999985, 105072962.50000308, 123572514.28576481, 103039814.28569387], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [557717400.0000013, 217494299.99999848, 97710157.14289077, 104560383.33328857, 98818785.71429427], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [804808199.9995703, 145316299.99983126, 94043187.50000584, 102488714.28575513, 102389357.14291334], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_10\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 10 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [33858.357132509685, 21570.053098417982, 17931.951649596445, 15031.24703342606, 12856.704783621133, 13217.631364842755, 13752.40154925209, 14158.554928287698, 16291.79828467407, 19550.381616508203, 23404.35310177283, 23205.286764936332], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [145914.33954359655, 76030.04197040669, 68772.11178339488, 62312.82317343137, 56159.78587382755, 51719.34419020101, 48535.97243800427, 44645.04458926293, 44210.11349302964, 43529.391454463344, 48519.50580573356, 36625.71311519222], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 500 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [98900542.85707654, 49213564.28576474, 32481114.285734035, 24127933.333349776, 15949166.66666298, 11932260.71429113, 7684871.604935864, 6136046.728974281, 5355518.571429586, 5103538.000003028, 3856418.0412341207, 3519849.740934066], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [228494533.33340836, 74110944.44453031, 50489110.000035, 35876015.789462574, 23832541.37930635, 18014897.36843857, 11929637.50000737, 8773572.972979702, 6543461.111117789, 4916952.941176005, 4261844.512196083, 4260097.093022121], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_2500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 2K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [2559967000.0001426, 1282695899.999453, 863696499.9996053, 661091900.0004287, 435640500.0003179, 326697049.99989337, 217506166.66668066, 164267100.0001883, 121834599.99996558, 95636900.00004499, 70992060.00002596, 60689918.18185829], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [4153688699.999293, 1577121799.9999862, 999466399.9996191, 751229499.9996811, 500239400.00028235, 375621350.000074, 252477166.66672206, 190841374.99999088, 126194860.00003235, 114451433.3332154, 78378177.77787374, 65656236.363627784], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_1000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [863.2724223609545, 1199.5239208628598, 1150.5110929858026, 875.495139733226, 905.1462740381147, 943.8653562656708, 1176.5151026389249, 1117.1101744176392, 1574.7970251713277, 1899.4592105268807, 2047.8376996811166, 2754.6197580638745], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [239.12471871795694, 993.2983630941786, 734.3979357791786, 347.99933035734347, 431.1715507410948, 233.20158569493464, 487.40065537951824, 296.3487878787418, 493.6928066792973, 509.50043604641087, 396.0932511737869, 426.3131474107398], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3892.6750000016564, 2550.5402877701167, 2543.303610107594, 2005.9129032249616, 2024.781081080299, 1893.734584448601, 1753.516120907744, 1575.6957013578703, 1474.6793176973738, 1450.199188640012, 1304.199626864924, 1382.9853515634481], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_10000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [24995.22500001409, 20401.8171428418, 21819.796874979147, 16063.281081064692, 18918.259183678576, 11774.160655730782, 11747.431645571965, 11700.133333330374, 21380.447826073658, 25750.955555546778, 26381.953846164553, 28146.021428580883], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [6700.27788461224, 7865.334090907213, 6414.663888891583, 8359.228409093786, 4203.702840909914, 3326.603825132865, 4188.728934012236, 2857.99221901916, 3676.2754189925413, 3729.014285714324, 3748.9309859179034, 3348.57685185044], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [105959.16666655587, 54654.66923082064, 52332.97692302586, 49357.07142859818, 41991.029411773896, 35743.05500001174, 30247.943478254612, 24344.693103432353, 20412.067647050528, 19978.605882362684, 17486.680000001797, 17482.43750000711], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_300000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 300K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [4031846.300000325, 728813.4000000355, 889849.3000006056, 994105.6999996363, 1049320.0000000796, 1522894.499999893, 997350.8000002766, 1162328.2000000472, 719202.5000003923, 590710.8999999764, 538416.5999994366, 389333.69999995193], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1021553.2000001986, 550953.599999957, 808491.700000559, 575432.6000005676, 428497.8999999112, 301521.5999998873, 271191.1500000497, 184467.9000000724, 160944.57500003045, 123093.80000003027, 101482.81428571083, 94858.25000001569], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [18044294.700000137, 7065072.499999587, 5501108.999999815, 4483277.099999214, 3272344.9000004623, 2602393.4999993797, 1837074.6999999029, 1465866.3999998681, 1134443.299999475, 1034357.9000000318, 910747.8999994782, 940844.6999996158], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"once_function_move\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Move Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Once Function\", \"values\": [13.297325000004482, 12.44779218750125, 15.474499999998313, 63.17638392853756], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [84.60370535721447, 87.93886214566874, 85.50149553577009, 99.84706250008912], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"once_function_queue\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Queue Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Inline Function\", \"values\": [1728.3028828328033, 2298.9828136373135, 4106.250000001564, 11814.530357144447], \"color\": \"#3498db\"}, {\"name\": \"Once Function\", \"values\": [4151.649530510759, 4444.022319605726, 5714.958035712568, 24791.373699199172], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [15993.8772321563, 15449.176339278178, 16863.257789670104, 27332.48588702272], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pipeline_bar\", \"suite\": \"pipeline\", \"type\": \"bar_h_colored\", \"title\": \"Pipeline Benchmark\", \"items\": [{\"name\": \"serial\", \"time_ns\": 517309400.00015837, \"color\": \"#95a5a6\"}, {\"name\": \"dispenso\", \"time_ns\": 323648450.00029165, \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"time_ns\": 345052449.9999119, \"color\": \"#3498db\"}, {\"name\": \"taskflow\", \"time_ns\": 279032433.33336526, \"color\": \"#f39c12\"}, {\"name\": \"dispenso par\", \"time_ns\": 17289443.24325287, \"color\": \"#2ecc71\"}, {\"name\": \"tbb par\", \"time_ns\": 15333088.888898298, \"color\": \"#3498db\"}, {\"name\": \"taskflow par\", \"time_ns\": 177765800.00008833, \"color\": \"#f39c12\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pool_allocator_1t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - Single-threaded\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [4841874.482754692, 20133108.82351588, 15900661.76469704, 86727966.66678551, 52209740.000034794, 338507800.0001158], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [151697.4553571312, 608897.767857083, 151710.62499998047, 610194.3750000568, 151843.12499993018, 613170.6473218352], \"color\": \"#2ecc71\"}, {\"name\": \"Arena\", \"values\": [87785.24173030464, 354860.6581531803, 87807.96839426439, 369143.4184678627, 102888.89285707878, 396455.46921698225], \"color\": \"#27ae60\"}, {\"name\": \"NoLock\", \"values\": [36529.972276425644, 149938.8169644281, 34454.390100169076, 137750.74327024948, 36677.227192370396, 148020.87053575568], \"color\": \"#3498db\"}, {\"name\": \"NoLock Arena\", \"values\": [38532.90736606547, 153872.82040979038, 42947.78008440383, 163558.2704584923, 38635.22138789477, 182755.6250000433], \"color\": \"#2980b9\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_2t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 2 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [1282449.9999997637, 5457345.251396258, 4142546.250000123, 134987949.99986786, 361473675.0000702, 1761543900.000106], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [740431.6964287513, 2283438.6363614835, 617903.2142857263, 2138911.7056853967, 632641.183035584, 2622329.166666587], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_8t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 8 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [4267534.7417848725, 43508459.459460296, 157427864.7058771, 1071541200.0004108, 2990842500.000326, 29085644200.00039], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [28401976.00002284, 119940283.33341096, 28545066.66665202, 125883900.00000799, 30857290.476195063, 148626225.00004363], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_16t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 16 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [29071062.000002712, 315045845.45448536, 1089591550.000023, 6414324400.000624, 20524383299.9995, 126245421600.00055], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [147053179.99996623, 575132300.000405, 139295816.66676918, 614732399.9994115, 143203459.99985877, 868872099.9998623], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"rw_lock_serial\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Serial Operations\", \"categories\": [\"2 iterations\", \"8 iterations\", \"32 iterations\", \"128 iterations\", \"512 iterations\"], \"groups\": [{\"name\": \"NopMutex\", \"values\": [1117013.8709677567, 751688.8531617045, 696887.0259483511, 743824.0641708043, 691569.5181911967], \"color\": \"#95a5a6\"}, {\"name\": \"std::shared_mutex\", \"values\": [19305188.888867836, 19369341.666662067, 19416355.55555068, 19409374.999996647, 19450205.55556059], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [16413025.58138789, 15095457.446806634, 14557727.083342798, 14445100.000000598, 14355700.000012396], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_2\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (2 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [19930965.714281358, 60408490.000008896, 337606033.3333347, 1040186500.0003453, 2435386000.000108, 5883264100.000815], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [16511460.465111203, 123026942.85712537, 651270000.0002952, 2099785399.999746, 12183545500.000036, 47369681199.99983], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_8\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (8 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [21549513.888885483, 75667622.22217625, 314955900.0003137, 1079131499.9996758, 2836406999.999781, 6595037799.999773], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [15019802.127658585, 89142955.55556843, 365472749.9997534, 1228708399.9999595, 4374994499.999957, 20147908899.999493], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_32\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (32 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [21245997.058833703, 72240179.9999716, 317916500.0001376, 996513100.0008113, 2575993400.000698, 6022973900.000579], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [15939482.222226312, 73564466.66674149, 281179333.33336014, 593563399.9997662, 2002235500.000097, 7846040399.999765], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_128\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (128 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [20044875.7575831, 74689120.00003912, 339969900.0001419, 889150599.9999936, 2100237499.999821, 5162757999.999485], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [14741991.836727927, 65577990.000019774, 168589574.99994177, 417482050.00021696, 1275850800.0006258, 3649717499.999497], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_512\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (512 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\", \"8 threads\", \"16 threads\", \"32 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [21410923.52940177, 77721177.77777667, 346075800.0001078, 910926999.9999014, 1920998399.9999168, 4707656599.999609], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [14390197.959166508, 59954890.90913577, 155646274.99998096, 373191650.0000807, 859905499.9995133, 2162233600.000036], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"simple_for_1000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [123.07973214287163, 123.07973214287163], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3730.466943069201, 3837.7929644697133, 3838.174185171489, 3846.697219407341, 3776.0300229212608, 3268.643969359266, 3907.4644168556215, 3930.4048728813827, 3989.4425319353586, 3010.6535108992152, 1198.065724584539, 1980.133482777899], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [530070.0000007055, 655714.800000169, 553511.0000000714, 683684.3999999473, 529424.0000002901, 566112.9000000074, 1008582.3999997956, 1520637.7000004067, 1579156.5999998057, 2060363.6999994705, 2633048.8999992665, 3749334.399999498], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [94489.09400372862, 55404.19955797613, 52165.437855183314, 49971.01224834739, 45114.74747472575, 44121.334580600385, 42392.62973476715, 40821.44385952365, 38385.39192397927, 38079.58828807129, 43669.55378971126, 31402.742625543535], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_1000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [319111.9549932008, 319111.9549932008], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3740731.016040369, 1883934.2318081206, 1263728.158845147, 958718.169399642, 641319.8662841313, 518581.76382622484, 356296.33818012616, 337820.90183176304, 200108.1678115046, 299582.39688189875, 115051.05351870028, 88691.24304753881], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [41611268.00000602, 30974307.999995288, 21487643.99999891, 16418552.000004638, 11053179.000000454, 8297672.999997304, 6320484.000007127, 6408918.571423783, 6326315.957450905, 6700124.034334154, 6581888.495575748, 6319112.107622977], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [2301049.999998864, 732378.3246071336, 552477.5715394203, 418109.99397952174, 314212.67787841236, 251644.77611938928, 184413.24946481115, 153759.2164419024, 122550.22002193381, 118082.17368332973, 107563.22610855168, 94512.12864547076], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_100000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [67764627.2727295, 67764627.2727295], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [374883649.99990153, 188763274.99992839, 125939799.99989338, 94210857.14296038, 62940163.63633339, 47400453.33334517, 31880404.54547676, 24358575.86207366, 17466794.73683942, 16123037.209306562, 14825679.591829576, 14073414.2857155], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [411014485.7143366, 385221509.09085953, 228389069.9999574, 170449150.0000586, 116734610.00000314, 87824870.00007677, 59986899.999967135, 52921700.00002443, 70141750.00003889, 60708569.99995158, 62731880.000046656, 60175500.0000594], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [194416074.9999355, 61618063.63632588, 41292594.11766885, 33157647.82608154, 20907515.151520785, 16060631.818184199, 14373813.207539398, 12140977.586207964, 11818566.101699278, 12474183.05084173, 15330244.444440823, 15240334.782625405], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_pool_1000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [24.277716282106763, 56.13552705407945, 195.84133619485556, 678.2534999993003, 404.57178354494965, 646.0160134384197, 915.6794753091253, 1070.1370646760308, 1043.2820189267852, 1117.476061121439, 1635.1648451739231, 1298.4027522947179], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3.6356116902166824, 102.4837588434942, 410.48458998371774, 228.35810276696577, 198.67492841240426, 212.9978291119281, 383.7573289902642, 239.66880503136946, 371.0842427619582, 436.0011147540807, 345.8839126687858, 316.0932635414927], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [110.34019622635448, 61.096116418232064, 65.82905245180723, 66.21044876082574, 73.65813631521854, 74.59586090976644, 89.01725894788872, 82.66290284639199, 199.71918079115676, 378.6000987169127, 687.1267167380328, 873.793603936454], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_10000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [241.26279310339356, 95.73643086366705, 1548.2915807556512, 7496.027027029724, 3877.95562130241, 9096.213095236159, 9134.03835617317, 10599.76578948121, 11601.289361699835, 10774.16290322177, 11690.830508487741, 12350.17499999458], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [32.0947395020109, 151.15673975203256, 4592.246391753506, 4338.003521131123, 3333.4457055227253, 1873.2697986560129, 3412.0469314068737, 3433.8157894739784, 4021.7894444443423, 3760.596315786595, 2546.2014218000245, 2850.483141764403], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [1394.85276752724, 830.3519695039215, 788.4571748878452, 804.4626575024355, 864.0049118391016, 806.9064889923275, 1084.3216088332003, 1462.9511247454159, 2309.0762411353767, 3841.8216494832936, 8936.300000000183, 10631.54754099175], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_1000000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [24174.65517242065, 53904.19069767949, 680157.2000003944, 676183.100000344, 410173.0500001395, 874569.3999999275, 917388.3000003116, 1147152.100000312, 1095964.3999995023, 1450257.8000001449, 1323019.2000000898, 1619255.3999999291], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [3181.654090907283, 19991.609090924834, 132134.42000014766, 380272.5499999724, 356584.6000001329, 326526.02500002104, 390302.8999998241, 366209.95000021136, 387441.5999998746, 352939.9499998363, 305708.70000004413, 173304.50000008568], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [754986.5999999384, 187431.95000001835, 189270.47500005754, 198268.33333354443, 269627.0000001277, 194687.624999915, 200951.36666683783, 211672.6666666485, 235006.60000020918, 544083.4000000905, 1025400.8000001705, 1310981.9999999672], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"small_buffer\", \"suite\": \"small_buffer\", \"type\": \"bar_h_colored\", \"title\": \"Small Buffer Allocator Benchmark\", \"items\": [{\"name\": \"newdelete[S]/8192\", \"time_ns\": 649918.5267858008, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192\", \"time_ns\": 122091.17857147638, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/8192/threads:16\", \"time_ns\": 60861.78125007298, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192/threads:16\", \"time_ns\": 14027.127511199009, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768\", \"time_ns\": 2327006.8273106236, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768\", \"time_ns\": 489625.53633217537, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768/threads:16\", \"time_ns\": 225898.00781389614, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768/threads:16\", \"time_ns\": 51777.78888078719, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192\", \"time_ns\": 513826.20000003953, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192\", \"time_ns\": 109757.37500004357, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192/threads:16\", \"time_ns\": 67333.4455817907, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192/threads:16\", \"time_ns\": 15188.683461341448, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768\", \"time_ns\": 4531621.249998352, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768\", \"time_ns\": 438479.1875003202, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768/threads:16\", \"time_ns\": 285637.53906283295, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768/threads:16\", \"time_ns\": 60007.86272320877, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192\", \"time_ns\": 915519.308036445, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192\", \"time_ns\": 139625.03013253893, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192/threads:16\", \"time_ns\": 75147.95312506096, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192/threads:16\", \"time_ns\": 14773.132812493373, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768\", \"time_ns\": 3777730.379743663, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768\", \"time_ns\": 558594.1071428481, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768/threads:16\", \"time_ns\": 394780.77256897377, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768/threads:16\", \"time_ns\": 64837.47395845304, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"legend\": [{\"name\": \"SmallBufferAllocator\", \"color\": \"#2ecc71\"}, {\"name\": \"new/delete\", \"color\": \"#e74c3c\"}]}, {\"id\": \"small_buffer_shared_bar\", \"suite\": \"small_buffer_shared\", \"type\": \"bar_h_colored\", \"title\": \"Small Buffer Shared Benchmark\", \"items\": [{\"name\": \"newdelete<kLargeSize>/32768\", \"time_ns\": 3153438.207545888, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kLargeSize>/32768/threads:16\", \"time_ns\": 380519.4754450879, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kLargeSize>/8192\", \"time_ns\": 1254287.3437496382, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kLargeSize>/8192/threads:16\", \"time_ns\": 74954.21875004146, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kMediumSize>/32768\", \"time_ns\": 4597018.831167612, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kMediumSize>/32768/threads:16\", \"time_ns\": 296599.54427193233, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kMediumSize>/8192\", \"time_ns\": 513510.35714251985, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kMediumSize>/8192/threads:16\", \"time_ns\": 61919.997480021404, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kSmallSize>/32768\", \"time_ns\": 2322325.000002159, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kSmallSize>/32768/threads:16\", \"time_ns\": 221986.53492717526, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kSmallSize>/8192\", \"time_ns\": 748380.3571426099, \"color\": \"#7f8c8d\"}, {\"name\": \"newdelete<kSmallSize>/8192/threads:16\", \"time_ns\": 60153.906249738044, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kLargeSize>/32768\", \"time_ns\": 595084.1071426437, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kLargeSize>/32768/threads:16\", \"time_ns\": 72366.75781250311, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kLargeSize>/8192\", \"time_ns\": 149054.9776785802, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kLargeSize>/8192/threads:16\", \"time_ns\": 15871.16015620893, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kMediumSize>/32768\", \"time_ns\": 491120.7142859959, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kMediumSize>/32768/threads:16\", \"time_ns\": 62205.6005859406, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kMediumSize>/8192\", \"time_ns\": 122679.41071432429, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kMediumSize>/8192/threads:16\", \"time_ns\": 14346.227820424781, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kSmallSize>/32768\", \"time_ns\": 546668.4821434293, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kSmallSize>/32768/threads:16\", \"time_ns\": 55517.51302087145, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kSmallSize>/8192\", \"time_ns\": 136748.11169155658, \"color\": \"#7f8c8d\"}, {\"name\": \"small buffer allocator<kSmallSize>/8192/threads:16\", \"time_ns\": 14595.566406251846, \"color\": \"#7f8c8d\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"summing_for_1000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [165.63020305552206, 165.63020305552206], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [283.97484404163015, 287.415294303854, 288.7592753538838, 291.2505429065487, 292.6986874961101, 297.2038260866358, 291.68175467479045, 297.40874013502855, 308.25913038902155, 324.9908315987843, 356.9433864665559, 419.15277892633566], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [95965.93034283393, 62567.788592751866, 66087.83472895667, 55719.6008768989, 53579.3209402647, 53853.236105647215, 47966.7218324109, 43952.141120723856, 42071.109001370045, 41295.14586041345, 44369.940513872105, 33112.1733469637], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_1000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [191584.62362719976, 191584.62362719976], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [186574.36813195448, 391835.8830147151, 267170.3406047968, 203913.19027185196, 137883.74354900772, 107803.5523420331, 92882.73067330717, 117187.36313277017, 29895.387872354004, 43855.310748823875, 56892.74349440751, 45718.8461538357], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [608633.9331620311, 248218.53795055265, 197207.87280019786, 174024.358974295, 135652.9222735869, 124713.75679935279, 99408.56622125838, 92679.01200873358, 77913.14240441729, 70674.81800470152, 69779.40696671692, 57817.8154824973], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_100000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [40467617.64707566, 40467617.64707566], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [41011788.23528993, 44761018.74996629, 29970426.086947557, 21354400.00000182, 16108543.181809926, 10993362.50000249, 7566056.470579283, 6707372.1739095915, 5014663.000001746, 4178838.690477061, 4101583.040938903, 4104495.321637294], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [50261871.42857452, 21100748.48485855, 14535400.000011355, 10938712.499992676, 7612709.999999165, 5862020.833334706, 5012698.999998975, 4375098.837213997, 4064921.019110611, 4039693.0232556006, 4083682.9411786958, 4098470.175438983], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"timed_task\", \"suite\": \"timed_task\", \"type\": \"grouped_bar_h_error\", \"title\": \"Timed Task - Scheduling Jitter\", \"categories\": [\"2ms (Normal)\", \"2ms (Steady)\", \"4ms (Normal)\", \"4ms (Steady)\", \"6ms (Normal)\", \"6ms (Steady)\", \"Mixed (Normal)\", \"Mixed (Steady)\"], \"groups\": [{\"name\": \"dispenso\", \"values\": [114.10507199445439, 210.6759080536653, 94.99403194593472, 122.64779616308293, 111.22424800323611, 156.4002840850341, 58.25143066871532, 169.9293040307555], \"errors\": [259.59161117679963, 327.74180372595737, 221.48459148240076, 248.50180966736076, 258.4484966445175, 283.9156838132939, 184.24238583588738, 295.2365190105025], \"color\": \"#2ecc71\"}, {\"name\": \"folly\", \"values\": [568.0985280046283, 919.2386400182342, 545.5392239974364, 892.1381915636856, 533.2746680010663, 848.7736196124131, 723.1684653297855, 792.7332290995415], \"errors\": [564.2962547763238, 562.0669852732883, 555.8913424860759, 492.95077899891294, 605.9270038487692, 454.4098151601485, 599.8303041159767, 539.7679052957852], \"color\": \"#9b59b6\"}], \"xaxis_label\": \"Mean Scheduling Error (us)\"}, {\"id\": \"trivial_compute_100\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [8194.632153224366, 8200.924125655556, 8208.993698898777, 8210.547223910802, 8211.580058653659, 8211.550915062888, 8225.209084263233, 8275.614111854047, 8283.037262208562, 8325.585679190948, 8419.918217231101, 8715.408653548191], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [39884.28930467646, 31430.38843723694, 31214.695230832833, 32296.577563510007, 31171.23190649365, 30344.09665979791, 29450.223880596433, 31696.94395757417, 32137.197921382132, 33922.67439030511, 39177.04973306321, 23799.781181623777], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_1000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [90999777.77784969, 90999777.77784969], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [90152174.99995743, 45173566.66668396, 30222656.521761127, 22694403.448283616, 15322123.913036825, 11436237.93103839, 7971884.615381986, 5826082.7586231055, 4384141.807909891, 3530944.4444437483, 3137914.9122825, 3131572.687223701], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [114842633.33325846, 45232699.999966525, 30166578.260832466, 22630087.096771486, 15176271.739145033, 11396609.677420553, 7612427.17391289, 5816072.1311472375, 4536531.944444909, 3924480.8743161066, 2749477.777775783, 2581395.6363642565], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_100000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 64], \"y\": [7970337799.99947, 7970337799.99947], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [7959612399.9999695, 4335119400.000622, 2660708999.9997697, 2002838999.999767, 1336128599.9999382, 1004162499.9994383, 673378100.0002637, 528924399.99959606, 354444800.0002376, 265958699.99982825, 284690399.9998176, 283763350.0002994], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64], \"y\": [11798446499.999954, 3921351299.9995146, 2611634500.0000367, 1959720800.0004685, 1307265999.9997995, 983014100.0002186, 658705300.0002925, 510544100.00051576, 524089900.0000354, 527799899.9999909, 279121349.9999685, 277920633.33314824], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}]}, {\"id\": \"android-SXR2230P-6c\", \"label\": \"Unknown (6 cores)\", \"machine\": {\"timestamp\": \"2026-03-13T21:39:24+00:00\", \"platform\": \"Android\", \"platform_release\": \"12\", \"platform_version\": \"SDK 32\", \"architecture\": \"aarch64\", \"processor\": \"arm64-v8a\", \"device_model\": \"Quest 3\", \"device_name\": \"eureka\", \"soc_manufacturer\": \"Qualcomm\", \"soc_model\": \"SXR2230P\", \"hardware\": \"\", \"cpu_implementer\": \"0x41\", \"cpu_part\": \"0xd4b\", \"cpu_variant\": \"0x0\", \"cpu_cores\": 6, \"cpu_max_freq_mhz\": 2054, \"memory_kb\": 7941372, \"memory_gb\": 7.5, \"kernel\": \"5.10.205-01593-g21f33663a190\", \"platform_id\": \"android-SXR2230P-6c\", \"compiler\": {\"compiler_id\": \"Clang\", \"compiler_version\": \"19.x (Android NDK r26b)\", \"build_type\": \"Release (opt)\", \"compiler_summary\": \"Clang 19.x (Android NDK r26b) Release (opt)\"}}, \"charts\": [{\"id\": \"cascading_parallel_for_default\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For\", \"traces\": [{\"name\": \"serial\", \"x\": [1000, 100000, 10000000], \"y\": [11202.182462469822, 1029693.8759103239, 102025825.99958986], \"color\": \"#95a5a6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_1000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 1K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6], \"y\": [11479.564282153204, 11359.95342418285, 11354.091228354944, 11362.63826854818, 11354.038655426712], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6], \"y\": [11261.29988727075, 13471.981386236224, 14205.151065086318, 14558.53206657101, 13972.97655239293], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [147090.64674729988, 139420.02387293856, 157708.99437164958, 171646.142055542, 188087.77158036386], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6], \"y\": [149690.08794803094, 124360.79122322708, 126672.07372210975, 141339.5555555142, 144893.0879623469], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_100000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 100K Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6], \"y\": [1057726.063909901, 730870.0419976538, 548037.2636942863, 429752.00655642076, 407500.9724916474], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6], \"y\": [1037306.705878858, 685366.4387260021, 496504.9889284689, 401480.11159571056, 320889.6151340309], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [1759704.7106895354, 925631.1461823646, 716468.145453421, 605852.2707438713, 569085.8455289241], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6], \"y\": [1753545.0937543828, 920307.4506618386, 674174.120193199, 567108.6428579948, 496408.31052544713], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"cascading_parallel_for_10000000\", \"suite\": \"cascading_parallel_for\", \"type\": \"line\", \"title\": \"Cascading Parallel For - 10M Elements\", \"traces\": [{\"name\": \"dispenso_blocking\", \"x\": [1, 2, 3, 4, 6], \"y\": [104531659.99994476, 71714668.74979159, 48331223.59996196, 41342794.28555082, 35476186.571551286], \"color\": \"#2ecc71\", \"dash\": \"dash\"}, {\"name\": \"dispenso_cascaded\", \"x\": [1, 2, 3, 4, 6], \"y\": [103815080.00015552, 67462584.75004652, 46207417.833102226, 38270970.999812044, 34649229.71449726], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [149613010.00039384, 75134707.99995048, 50615046.80015787, 40938315.14260923, 36961543.85709503], \"color\": \"#3498db\", \"dash\": \"dash\"}, {\"name\": \"tbb_task_group\", \"x\": [1, 2, 3, 4, 6], \"y\": [150388842.99974597, 74963484.00036368, 50236367.8333495, 40492846.28568525, 36228642.874903016], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"concurrent_vector_serial\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Serial/Access Operations\", \"categories\": [\"push back serial\", \"push back serial reserve\", \"iterate\", \"iterate reverse\", \"lower bound\", \"index\", \"random\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [3072432.769241149, 1845768.324510693, 136768.566649875, 223231.17820138438, 79608262.99995461, 136777.56347178397, 4724779.779650616], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [5289420.59617503, 0, 1072412.1787084688, 821501.9707618625, 99955079.33308546, 775122.2265192381, 5496402.788454501], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [26558054.69985353, 25676702.36368775, 1246598.2711081677, 3655440.7142830314, 108657354.33314209, 3691881.5394768133, 6093960.042562685], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [14667761.894758627, 14737101.263132278, 833397.4005930811, 854359.2522822755, 74007611.74994841, 1895850.0608204228, 5669632.860008278], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"concurrent_vector_parallel\", \"suite\": \"concurrent_vector\", \"type\": \"grouped_bar_h\", \"title\": \"Concurrent Vector - Parallel Operations\", \"categories\": [\"parallel\", \"parallel reserve\", \"parallel clear\", \"parallel grow by 10\", \"parallel grow by 100\", \"parallel grow by max\"], \"groups\": [{\"name\": \"std::vector\", \"values\": [136648068.9994205, 134157044.33343005, 134396732.33309197, 18439793.500047844, 3325676.6259528515, 985640.7004329821], \"color\": \"#808080\"}, {\"name\": \"std::deque\", \"values\": [143536004.00014934, 0, 143588399.6667447, 22642562.57895843, 10747807.777766462, 6101889.086212082], \"color\": \"#FF8C00\"}, {\"name\": \"tbb::concurrent_vector\", \"values\": [75401752.49960157, 75114903.25032355, 72413015.00016561, 9255702.333333222, 886992.6044306201, 283090.6588836664], \"color\": \"#4285F4\"}, {\"name\": \"dispenso::ConcurrentVector\", \"values\": [34231539.83339944, 34488082.8749865, 32486044.88888102, 3593392.1219510944, 432565.53023335675, 118329.2334460896], \"color\": \"#34A853\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"for_each_1000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1K Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6], \"y\": [909.9793032527018, 1278.5740430670805, 1104.874453886845, 1208.859321531916, 1662.587611011352], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6], \"y\": [6150.10428529867, 16516.506474381313, 15588.800591252735, 16748.795263095326, 17642.94723584601], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6], \"y\": [8002.854016110876, 13821.888177566336, 16791.0029416874, 15866.502046227826, 18214.411768647333], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6], \"y\": [2665.8799782919, 4726.791070493045, 5366.31389606957, 5521.94104865395, 6092.973243999766], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_1000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 1M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6], \"y\": [899356.8942339781, 604533.1077561498, 413785.9590039493, 341192.3312416144, 256581.11061489768], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6], \"y\": [6122648.934805234, 16782241.2940415, 16720896.294132486, 16135785.94119377, 16500798.23529642], \"color\": \"#e67e22\"}, {\"name\": \"for_each_n_list\", \"x\": [1, 2, 3, 4, 6], \"y\": [8033067.742819965, 18143033.000039093, 17601007.562575433, 17037403.64706284, 16896717.35295954], \"color\": \"#3498db\"}, {\"name\": \"for_each_n_set\", \"x\": [1, 2, 3, 4, 6], \"y\": [2715.8142249951875, 4857.855707617169, 5454.740410417156, 5613.515208891196, 6182.183584493816], \"color\": \"#9b59b6\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_each_100000000\", \"suite\": \"for_each\", \"type\": \"line\", \"title\": \"For Each - 100M Elements\", \"traces\": [{\"name\": \"for_each_n\", \"x\": [1, 2, 3, 4, 6], \"y\": [87534383.66632812, 58416068.40003805, 39041313.42850243, 33879019.66662967, 25401328.272809304], \"color\": \"#2ecc71\"}, {\"name\": \"for_each_n_deque\", \"x\": [1, 2, 3, 4, 6], \"y\": [611865999.0006562, 1662459645.0001264, 1658312666.000711, 1654381362.0010042, 1661199853.000653], \"color\": \"#e67e22\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"for_latency_default\", \"suite\": \"for_latency\", \"type\": \"line\", \"title\": \"For Latency\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [44590499.33332911, 37393657.00000365, 35743766.62504619, 34446670.12490754, 34135986.50013228], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [44767365.66690913, 37070648.2501646, 34706748.24984599, 33506884.875123434, 32804241.624944553], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"future\", \"suite\": \"future\", \"type\": \"grouped_bar_v\", \"title\": \"Future/Async Tree Build Benchmark\", \"categories\": [\"Small\", \"Medium\", \"Large\"], \"groups\": [{\"name\": \"serial\", \"values\": [685395.1390217933, 5483278.745112543, 48867235.833313316], \"color\": \"#95a5a6\"}, {\"name\": \"std::async\", \"values\": [518473436.9995567, 42016983.285585806, 336012690.0006435], \"color\": \"#e74c3c\", \"error_indices\": [1, 2]}, {\"name\": \"folly::Future\", \"values\": [5040517.607150312, 42016983.285585806, 336012690.0006435], \"color\": \"#e67e22\"}, {\"name\": \"dispenso::Future\", \"values\": [864298.1775719081, 6090607.840881355, 49559015.4283231], \"color\": \"#3498db\"}, {\"name\": \"dispenso::TaskSet\", \"values\": [578304.3958742672, 4553998.2741707545, 36112145.62511122], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso::TaskSet (bulk)\", \"values\": [569903.0894325783, 4498795.806431454, 35381546.50004799], \"color\": \"#1e8449\"}, {\"name\": \"dispenso::when_all\", \"values\": [2022280.929995759, 14852545.315749777, 125996678.99939959], \"color\": \"#9b59b6\"}], \"yaxis_unit\": \"ns\", \"xaxis\": \"Tree Size\"}, {\"id\": \"graph_bar\", \"suite\": \"graph\", \"type\": \"bar_h_colored\", \"title\": \"Graph Benchmark\", \"items\": [{\"name\": \"taskflow build big tree\", \"time_ns\": 23287857.454554547, \"color\": \"#f39c12\"}, {\"name\": \"build big tree (Graph)\", \"time_ns\": 4741128.661037893, \"color\": \"#2ecc71\"}, {\"name\": \"build big tree (BiProp)\", \"time_ns\": 5852130.562516321, \"color\": \"#27ae60\"}, {\"name\": \"build bi prop dependency chain\", \"time_ns\": 120323.65335046638, \"color\": \"#2ecc71\"}, {\"name\": \"build bi prop dependency group\", \"time_ns\": 1363.148034890439, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (Graph)\", \"time_ns\": 24804.563219368763, \"color\": \"#2ecc71\"}, {\"name\": \"build dependency chain (BiProp)\", \"time_ns\": 25884.07397837702, \"color\": \"#27ae60\"}, {\"name\": \"execute dependency chain (Graph)\", \"time_ns\": 13032.079503526009, \"color\": \"#2ecc71\"}, {\"name\": \"execute dependency chain (BiProp)\", \"time_ns\": 12996.761960635667, \"color\": \"#27ae60\"}, {\"name\": \"forward propagator node (Graph)\", \"time_ns\": 5547313.647077638, \"color\": \"#2ecc71\"}, {\"name\": \"forward propagator node (BiProp)\", \"time_ns\": 5575856.470671829, \"color\": \"#27ae60\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"graph_scene_bar\", \"suite\": \"graph_scene\", \"type\": \"bar_h_colored\", \"title\": \"Graph Scene Benchmark\", \"items\": [{\"name\": \"scene graph parallel for\", \"time_ns\": 78663150.3336442, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph taskflow\", \"time_ns\": 47062964.83315479, \"color\": \"#f39c12\"}, {\"name\": \"scene graph concurrent task set\", \"time_ns\": 46913294.33323214, \"color\": \"#2ecc71\"}, {\"name\": \"scene graph partial revaluation\", \"time_ns\": 1092137.1517884014, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_default\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool\", \"traces\": [{\"name\": \"dispenso_very_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [100065.32266622041, 100077.6663331635, 100077.85699963279, 100074.0899999073, 100078.62100004179], \"color\": \"#76d7c4\"}, {\"name\": \"tbb_very_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [100073.41266646108, 100091.78066684399, 100088.4823333763, 100109.03766669799, 100089.45433340462], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [5.388512047507226, 5.374452108898085, 6.202122315257175, 21.59938240001793, 250.70977954493918], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [86.42811145395417, 363.28877028350274, 262.9761530415255, 264.7457232821323, 277.6129106769637], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_10000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [29.967821740861904, 29.369898961096787, 30.019263103390394, 40.114500802134486, 403.68798921687477], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [863.6351815389039, 2800.4709999975926, 2671.878269228938, 2657.755219046348, 2758.0932211409304], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"idle_pool_1000000\", \"suite\": \"idle_pool\", \"type\": \"line\", \"title\": \"Idle Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [2534.003504579315, 2567.7155625122136, 2501.058044236316, 2490.3746846715107, 3068.1916428615555], \"color\": \"#48c9b0\"}, {\"name\": \"tbb_mostly_idle\", \"x\": [1, 2, 3, 4, 6], \"y\": [86042.94266660872, 348001.9100006757, 263200.18300066295, 267316.64200087835, 275950.7569990092], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_100000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 100K Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [1351112.7536304593, 365026.70239557186, 551542.7495414589, 2004376.8640025519, 7441747.191517199], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [1307148.6915816134, 390006.14878528926, 356044.3936150428, 1996112.846779485, 6121975.054570198], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [1531059.7486287937, 592366.9939032308, 863157.0873499679, 4771257.6274623675, 8007173.833347123], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_4000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 4M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [54312310.250224985, 19111224.13330304, 21933038.999962334, 26438269.727309074, 34562191.00007729], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [54404838.80011016, 19081154.66661305, 20672425.923084326, 25814794.272677813, 32391594.666680448], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [55392414.25003638, 21749720.08333498, 26127320.299929123, 53764961.83331862, 81298966.5000714], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"locality_32000000\", \"suite\": \"locality\", \"type\": \"line\", \"title\": \"Locality - 32M Elements\", \"traces\": [{\"name\": \"dispenso_auto\", \"x\": [1, 4, 16, 64, 128], \"y\": [426584626.0004764, 150174259.99940315, 155882906.49975532, 162923011.0002027, 174092256.99975652], \"color\": \"#00bcd4\"}, {\"name\": \"dispenso_static\", \"x\": [1, 4, 16, 64, 128], \"y\": [424796084.00026333, 155418166.49965766, 157455667.0002494, 160290537.00003713, 169323480.49977008], \"color\": \"#1e8449\"}, {\"name\": \"tbb\", \"x\": [1, 4, 16, 64, 128], \"y\": [459815827.00005674, 153945093.49971485, 177028611.00042355, 274840861.00048447, 362659202.9995663], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_10\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 10 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [6343.2366493602185, 4289.370571703738, 3656.074971468738, 3317.115459337133, 3217.950806010761], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [126296.64252772507, 104807.28426580124, 109019.39847882054, 115444.83776039345, 122594.53968947381], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 500 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [166220068.5004791, 81883931.66650106, 52152640.5998884, 40874205.49997963, 27851096.624999627], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [170237959.49990016, 83094608.9996966, 52809640.59966209, 40248849.49982758, 26339551.222311758], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_for_2500\", \"suite\": \"nested_for\", \"type\": \"line\", \"title\": \"Nested For - 2K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [4815991470.000881, 2404516853.9996667, 1666806416.0003269, 1386478680.0004368, 941762021.0006135], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [4813509749.9998665, 2407204145.9985485, 1606369535.00034, 1254140176.999499, 852626334.9995134], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_1000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [874.2171607743046, 593.5836369414889, 648.5171113622941, 617.9984957617631, 507.53605919492], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [193.48733816334627, 315.5924117651943, 239.9514868088869, 198.72244825259818, 156.18827609792484], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6], \"y\": [47046.9144999394, 32721.63522221187, 26256.294300037553, 22499.37291662718, 19685.99892864274], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [3052.7143626386533, 1725.198216050041, 1311.0043849811634, 1139.8819183731187, 980.0156338993258], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_10000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [26738.820399987162, 8693.613545498616, 11112.886519986205, 12384.612999994715, 14443.582149942813], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [5180.161592593154, 4850.9469482676905, 3886.2980704258184, 3099.1849222118617, 2849.2425673133625], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6], \"y\": [1363512.9480007892, 985011.9729999278, 779945.5469994427, 747863.5650004435, 700121.8929999595], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [92605.3910000822, 47964.084666697694, 34299.93174995616, 27905.627799918875, 21975.713999988027], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"nested_pool_300000\", \"suite\": \"nested_pool\", \"type\": \"line\", \"title\": \"Nested Pool - 300K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [4296235.063000495, 572158.9629993105, 687859.5990001486, 832972.6869997103, 1237114.3419986765], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [785011.7970010615, 404659.6230000432, 319369.9280000146, 268867.1619998786, 262039.9740007997], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [15115136.610000264, 7559557.2109996285, 5225128.906000463, 4189370.2089982983, 2970313.525000165], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"skipped_libs\": [{\"name\": \"folly\", \"color\": \"#9b59b6\"}]}, {\"id\": \"once_function_move\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Move Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Once Function\", \"values\": [6.280473378439153, 6.1327959880093506, 6.299513564978442, 25.703163273476257], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [66.94997690153612, 65.9076352199143, 69.33510034138529, 84.79090654403211], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"once_function_queue\", \"suite\": \"once_function\", \"type\": \"grouped_bar_h\", \"title\": \"Once Function - Queue Operations\", \"categories\": [\"Small\", \"Medium\", \"Large\", \"Extra Large\"], \"groups\": [{\"name\": \"Inline Function\", \"values\": [1392.9191585353794, 3046.6177007596016, 5501.283976281524, 14178.460244519238], \"color\": \"#3498db\"}, {\"name\": \"Once Function\", \"values\": [3141.3188963538773, 3957.286294911814, 5558.722151877583, 256301.4055755807], \"color\": \"#2ecc71\"}, {\"name\": \"Std Function\", \"values\": [15440.894206410487, 30537.81559359709, 42701.67192972245, 133131.56717196046], \"color\": \"#e74c3c\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pipeline_bar\", \"suite\": \"pipeline\", \"type\": \"bar_h_colored\", \"title\": \"Pipeline Benchmark\", \"items\": [{\"name\": \"serial\", \"time_ns\": 518612030.99906564, \"color\": \"#95a5a6\"}, {\"name\": \"dispenso\", \"time_ns\": 227088720.00112024, \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"time_ns\": 485735985.9997814, \"color\": \"#3498db\"}, {\"name\": \"taskflow\", \"time_ns\": 508602915.00066525, \"color\": \"#f39c12\"}, {\"name\": \"dispenso par\", \"time_ns\": 106832510.49977116, \"color\": \"#2ecc71\"}, {\"name\": \"tbb par\", \"time_ns\": 147814415.99916434, \"color\": \"#3498db\"}, {\"name\": \"taskflow par\", \"time_ns\": 506115882.99943835, \"color\": \"#f39c12\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"pool_allocator_1t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - Single-threaded\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [3171504.2272770177, 12764288.681782173, 11260113.600001205, 45310542.666811675, 11044482.31999413, 44925846.499912344], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [185259.30033076904, 743786.1866686338, 185060.52475269898, 742972.157332891, 185043.61543511794, 743036.143618117], \"color\": \"#2ecc71\"}, {\"name\": \"Arena\", \"values\": [102987.60727429499, 412765.5646364461, 102992.08486372787, 412837.4243338856, 102989.20286616778, 412740.4918270537], \"color\": \"#27ae60\"}, {\"name\": \"NoLock\", \"values\": [73305.2055512174, 293794.134041549, 73700.7398799987, 294520.71868323715, 73380.2209730875, 294322.11583446217], \"color\": \"#3498db\"}, {\"name\": \"NoLock Arena\", \"values\": [47560.18005078068, 190938.68360479805, 47479.94698640253, 190626.61690568112, 47662.57159827656, 193618.04211949557], \"color\": \"#2980b9\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_2t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 2 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [6299882.919993252, 25321330.599945214, 21622887.599914975, 80309122.6000106, 26747051.266769025, 100668801.60011351], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [1403284.6926810879, 5504953.404765512, 1470129.201972193, 5476923.529403946, 1400960.111670872, 5937744.0000166735], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_8t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 8 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [20791680.333382424, 93871224.66675161, 107697367.49989533, 306510603.99941343, 113016521.49995789, 532290417.000695], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [25029213.85712398, 120719413.00018807, 31215094.25000113, 107461886.00023742, 27231860.444468718, 125520012.4996918], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"pool_allocator_16t\", \"suite\": \"pool_allocator\", \"type\": \"grouped_bar_h\", \"title\": \"Pool Allocator - 16 Threads\", \"categories\": [\"S/8K\", \"S/32K\", \"M/8K\", \"M/32K\", \"L/8K\", \"L/32K\"], \"groups\": [{\"name\": \"malloc/free\", \"values\": [34918624.764673844, 160791669.74986947, 153353661.33331263, 699948767.0000235, 170880763.66659757, 740298406.9995], \"color\": \"#e74c3c\"}, {\"name\": \"PoolAllocator\", \"values\": [93409683.74999647, 353324905.0005907, 98188561.7999069, 350214514.33325034, 106705051.11112207, 371980714.0005287], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"log_scale\": true}, {\"id\": \"rw_lock_serial\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Serial Operations\", \"categories\": [\"2 iterations\", \"8 iterations\", \"32 iterations\", \"128 iterations\", \"512 iterations\"], \"groups\": [{\"name\": \"NopMutex\", \"values\": [929544.7558530779, 934083.3924928682, 917672.5639351434, 937324.9200022352, 936990.6565675302], \"color\": \"#95a5a6\"}, {\"name\": \"std::shared_mutex\", \"values\": [44912330.833237015, 44319648.49997409, 43844136.33336711, 43696445.33320146, 43647391.49999271], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [14812931.894802636, 13551633.28575838, 13201997.85714933, 13036749.809543833, 12991488.045455215], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_2\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (2 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [45217851.83351312, 430456606.00000703, 2176589904.998764], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [14808208.68422789, 187428247.9993781, 887020244.9998033], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_8\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (8 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [44433893.16656976, 362874046.9994227, 1909084409.0005703], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [13540147.666693276, 125367486.50018126, 454458952.00100493], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_32\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (32 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [44250785.66691809, 361754671.99973357, 1422208474.999934], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [13174316.809541086, 88666536.66700585, 243517941.00039116], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_128\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (128 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [43780099.833384156, 417823947.9988406, 911962902.9992211], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [12997451.590887398, 77645372.25011736, 167798219.9998951], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"rw_lock_parallel_512\", \"suite\": \"rw_lock\", \"type\": \"grouped_bar_h\", \"title\": \"RW Lock - Parallel (512 iterations)\", \"categories\": [\"1 threads\", \"2 threads\", \"4 threads\"], \"groups\": [{\"name\": \"std::shared_mutex\", \"values\": [43770282.16670927, 442135512.9998119, 669293295.0008981], \"color\": \"#e74c3c\"}, {\"name\": \"dispenso::RWLock\", \"values\": [12963905.181839602, 73627051.75000884, 147917020.0000226], \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\"}, {\"id\": \"simple_for_1000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [3.6400160752236843e-07, 3.6400160752236843e-07], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [784.9189316885689, 784.2254898128845, 785.0735280539584, 786.0184957256699, 785.3296723368471], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6], \"y\": [475413.3799997362, 487887.13199974154, 388376.7569986958, 339490.451000529, 317386.021000857], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [91045.54227707216, 92005.24330578845, 100232.79299280152, 101569.0491261831, 109073.37948739853], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_1000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [3.639997885329649e-07, 3.639997885329649e-07], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [843640.1114456849, 600138.8365578067, 409896.41666740115, 331123.7943006877, 252982.2695995691], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6], \"y\": [22203000.870360013, 23582887.766663894, 13557144.579990564, 10253444.769987253, 7517060.129994206], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [1324021.5539895494, 712905.9462911759, 531021.5578755296, 450605.52312580135, 395989.24783842673], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_for_100000000\", \"suite\": \"simple_for\", \"type\": \"line\", \"title\": \"Simple For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [3.650002327049151e-07, 3.650002327049151e-07], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [75920489.24971095, 57270130.600227274, 38690896.71440763, 33102457.750146642, 25235859.5454015], \"color\": \"#2ecc71\"}, {\"name\": \"taskflow\", \"x\": [1, 2, 3, 4, 6], \"y\": [152300084.33294037, 151988021.14303234, 156515455.9091091, 147216677.0001119, 150376599.16667205], \"color\": \"#f39c12\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [112580809.66642107, 56153088.80005614, 37901834.143018015, 29182514.44457888, 25143932.36362428], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\", \"no_auto_zoom\": true}, {\"id\": \"simple_pool_1000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [25.95345415691071, 18.872207139982944, 223.55017048906728, 290.80397533440083, 444.4975647583119], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [3.8957624627460876, 20.73410827078801, 116.03614734546915, 118.67673490973019, 140.77349376445852], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6], \"y\": [672.7934915669534, 622.4681580112516, 652.3204124424674, 663.499406325511, 679.2606675040469], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [90.03957474230924, 259.0293478247569, 262.4333990563585, 273.57316764154865, 298.0061547389893], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_10000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 10K Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [258.86781515741933, 156.22130923273875, 2019.6027999918442, 2928.119788451183, 4294.932967211219], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [38.01663068179157, 525.5522752972432, 1082.700568893213, 1192.9172217617227, 1296.6645304360377], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6], \"y\": [6360.496613607128, 5870.0094468030275, 6281.448295463964, 6450.842250036327, 6499.728116301243], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [910.0875213155886, 2630.096231465965, 2660.879733334046, 2662.4582912597707, 2860.4586210444963], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"simple_pool_1000000\", \"suite\": \"simple_pool\", \"type\": \"line\", \"title\": \"Simple Pool - 1M Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [25882.57354545931, 30368.695111165936, 225749.34499971278, 281113.4650000895, 423006.24000017706], \"color\": \"#2ecc71\"}, {\"name\": \"dispenso_bulk\", \"x\": [1, 2, 3, 4, 6], \"y\": [3724.5934266684344, 19238.253357018817, 118575.74099940393, 118438.63149988465, 129276.393499822], \"color\": \"#1e8449\", \"dash\": \"dash\"}, {\"name\": \"folly\", \"x\": [1, 2, 3, 4, 6], \"y\": [642591.6270000016, 578158.0260008923, 615674.4370000524, 631774.0729991783, 644738.7099997286], \"color\": \"#9b59b6\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [228194.91799964453, 265269.81800088834, 262043.30699874845, 270964.8700001708, 307126.74900132697], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"small_buffer\", \"suite\": \"small_buffer\", \"type\": \"bar_h_colored\", \"title\": \"Small Buffer Allocator Benchmark\", \"items\": [{\"name\": \"newdelete[S]/8192\", \"time_ns\": 584017.6375007407, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192\", \"time_ns\": 105516.16572744322, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/8192/threads:16\", \"time_ns\": 304266.9990218627, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/8192/threads:16\", \"time_ns\": 14257.33724899483, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768\", \"time_ns\": 2515437.8482251815, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768\", \"time_ns\": 421473.33383342664, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[S]/32768/threads:16\", \"time_ns\": 1650520.7968506853, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[S]/32768/threads:16\", \"time_ns\": 67319.2164276847, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192\", \"time_ns\": 843822.1891927177, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192\", \"time_ns\": 112088.35972895606, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/8192/threads:16\", \"time_ns\": 522474.75521246163, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/8192/threads:16\", \"time_ns\": 13103.715444592523, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768\", \"time_ns\": 3519757.7341667837, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768\", \"time_ns\": 447662.1182107373, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[M]/32768/threads:16\", \"time_ns\": 2673324.847648928, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[M]/32768/threads:16\", \"time_ns\": 83240.86666675612, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192\", \"time_ns\": 1198022.0641016474, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192\", \"time_ns\": 114935.6353612535, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/8192/threads:16\", \"time_ns\": 632238.6276001643, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/8192/threads:16\", \"time_ns\": 17412.032122255594, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768\", \"time_ns\": 4918945.105249836, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768\", \"time_ns\": 458002.61174738454, \"color\": \"#2ecc71\"}, {\"name\": \"newdelete[L]/32768/threads:16\", \"time_ns\": 2408651.7695067753, \"color\": \"#e74c3c\"}, {\"name\": \"small buffer allocator[L]/32768/threads:16\", \"time_ns\": 78231.75781295355, \"color\": \"#2ecc71\"}], \"xaxis_unit\": \"ns\", \"legend\": [{\"name\": \"SmallBufferAllocator\", \"color\": \"#2ecc71\"}, {\"name\": \"new/delete\", \"color\": \"#e74c3c\"}]}, {\"id\": \"summing_for_1000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1K Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [251.80944507283513, 251.80944507283513], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [316.497034359714, 315.0814294150636, 315.71763249400396, 316.05906242349005, 316.64861844198214], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [90270.4190884545, 91385.99322991195, 90688.41631455503, 100682.43566867914, 108105.93506971282], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_1000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [263624.59548326954, 263624.59548326954], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [264033.47058854304, 135175.76986459055, 94069.00651105503, 95777.05272045032, 100219.8986292068], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [361091.89766770863, 226209.27751286596, 197604.07426051615, 202477.5891421317, 222307.40308201284], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"summing_for_100000000\", \"suite\": \"summing_for\", \"type\": \"line\", \"title\": \"Summing For - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [27690278.79985515, 27690278.79985515], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [26737148.50006945, 14624502.526299022, 12813765.454583602, 12872484.68179314, 13727931.050016195], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [27508091.299932856, 14526300.789408483, 12690290.09092099, 13073473.523815794, 13904092.550001225], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"timed_task\", \"suite\": \"timed_task\", \"type\": \"grouped_bar_h_error\", \"title\": \"Timed Task - Scheduling Jitter\", \"categories\": [\"2ms (Normal)\", \"2ms (Steady)\", \"4ms (Normal)\", \"4ms (Steady)\", \"6ms (Normal)\", \"6ms (Steady)\", \"Mixed (Normal)\", \"Mixed (Steady)\"], \"groups\": [{\"name\": \"dispenso\", \"values\": [13.026822916666122, 19.57994793744866, 14.833593750000032, 14.620833376589697, 17.78177083333242, 18.441666644356136, 16.13559027778929, 16.044704889427603], \"errors\": [9.531265906036618, 82.6768700793036, 8.592811971375008, 12.271914481560083, 15.400723025035576, 35.79859605078633, 45.6681620180489, 57.3418443833851], \"color\": \"#2ecc71\"}, {\"name\": \"folly\", \"values\": [74.70572916667035, 64.17109385951032, 83.56223958333587, 76.62213528658049, 95.74322916667717, 66.45494789463045, 71.40833333333728, 62.134722133525635], \"errors\": [133.00534118277457, 9.798314414891916, 270.05312700179473, 101.70333856705504, 409.1264225462286, 9.144976228540143, 196.9415560385558, 7.071315222038903], \"color\": \"#9b59b6\"}], \"xaxis_label\": \"Mean Scheduling Error (us)\"}, {\"id\": \"trivial_compute_100\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100 Elements\", \"traces\": [{\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [1414.8151024542524, 1414.4553178160272, 1415.6990758309155, 1416.666757713665, 1413.2402885015313], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [89707.3289211519, 90376.59711030315, 89685.87830816176, 96953.10747812747, 104725.39985131778], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_1000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 1M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [109626069.66677414, 109626069.66677414], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [108036694.66622524, 54460974.199901104, 36234879.87488261, 27627096.499963958, 19139120.46158937], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [109009785.33330393, 54629807.600213096, 36805036.25014353, 27842325.69993037, 20210388.928587366], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}, {\"id\": \"trivial_compute_100000000\", \"suite\": \"trivial_compute\", \"type\": \"line\", \"title\": \"Trivial Compute - 100M Elements\", \"traces\": [{\"name\": \"serial\", \"x\": [1, 6], \"y\": [1486211970.9996479, 1486211970.9996479], \"color\": \"#95a5a6\", \"dash\": \"dash\", \"baseline\": true}, {\"name\": \"dispenso\", \"x\": [1, 2, 3, 4, 6], \"y\": [1425677068.9989934, 735477416.9998564, 501226352.00023067, 376238369.9995553, 258120546.99963483], \"color\": \"#2ecc71\"}, {\"name\": \"tbb\", \"x\": [1, 2, 3, 4, 6], \"y\": [1431572797.9992516, 716690019.0004526, 477958485.00027204, 371549829.000287, 251682889.0002216], \"color\": \"#3498db\"}], \"xaxis\": \"Threads\", \"yaxis_unit\": \"ns\"}]}];\nlet currentPlatformIdx = 0;\nlet currentTheme = 'dark';\n\n// ─── Time unit helpers ─────────────────────────────────────────\nfunction autoUnit(maxNs) {\n  if (maxNs >= 1e9) return { scale: 1e9, label: 's' };\n  if (maxNs >= 1e6) return { scale: 1e6, label: 'ms' };\n  if (maxNs >= 1e3) return { scale: 1e3, label: 'us' };\n  return { scale: 1, label: 'ns' };\n}\n\n// ─── Theme ─────────────────────────────────────────────────────\nfunction themeLayout() {\n  const dark = currentTheme === 'dark';\n  return {\n    paper_bgcolor: dark ? '#1c2128' : '#fff',\n    plot_bgcolor: dark ? '#0d1117' : '#f6f8fa',\n    font: { color: dark ? '#e6edf3' : '#1f2328', family: '-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif', size: 12 },\n    xaxis: { gridcolor: dark ? '#21262d' : '#eaeef2', zerolinecolor: dark ? '#30363d' : '#d0d7de' },\n    yaxis: { gridcolor: dark ? '#21262d' : '#eaeef2', zerolinecolor: dark ? '#30363d' : '#d0d7de' },\n    legend: { bgcolor: dark ? 'rgba(22,27,34,0.9)' : 'rgba(255,255,255,0.95)', bordercolor: dark ? '#30363d' : '#d0d7de', borderwidth: 1 },\n    modebar: { orientation: 'h', bgcolor: 'transparent', activecolor: dark ? '#58a6ff' : '#0969da' },\n  };\n}\n\nconst plotlyConfig = { responsive: true, scrollZoom: true, displayModeBar: true, modeBarButtonsToRemove: ['lasso2d','select2d'], displaylogo: false };\n\n// Pin the time axis lower bound to zero on any zoom/pan.\n// Preserves the zoom span so repeated zoom in/out doesn't drift.\nfunction pinZeroAxis(chartId, axis) {\n  const el = document.getElementById('chart-' + chartId);\n  if (!el) return;\n  let pinning = false;\n  el.on('plotly_relayout', function(ed) {\n    if (pinning) return;\n    const key0 = axis + '.range[0]';\n    const key1 = axis + '.range[1]';\n    // Check if the lower bound moved away from zero\n    if (key0 in ed && ed[key0] !== 0) {\n      const lo = ed[key0];\n      const hi = key1 in ed ? ed[key1] : el.layout[axis].range[1];\n      const span = hi - lo;  // preserve intended zoom level\n      pinning = true;\n      Plotly.relayout(el, { [key0]: 0, [key1]: span }).then(() => { pinning = false; });\n    }\n  });\n}\n\n// ─── Renderers ─────────────────────────────────────────────────\nfunction renderLine(cfg) {\n  const allY = cfg.traces.flatMap(t => t.baseline ? [] : t.y);  // exclude serial baseline\n  const maxY = allY.length > 0 ? Math.max(...allY) : 1;\n  const u = autoUnit(maxY);\n  const scaledAll = allY.map(v => v / u.scale);\n\n  // Auto-zoom: compare per-trace medians to detect when one trace dominates\n  const traceMedians = cfg.traces.filter(t => !t.baseline).map(t => {\n    const sv = [...t.y].filter(v => v > 0).sort((a,b) => a - b);\n    return sv.length > 0 ? sv[Math.floor(sv.length / 2)] / u.scale : 0;\n  }).filter(v => v > 0).sort((a,b) => a - b);\n  const maxTraceMedian = traceMedians.length > 0 ? traceMedians[traceMedians.length - 1] : 1;\n  const minTraceMedian = traceMedians.length > 0 ? traceMedians[0] : 1;\n  const autoZoom = !cfg.no_auto_zoom && traceMedians.length >= 2 && maxTraceMedian / minTraceMedian > 5;\n  // Zoom to show the competitive traces: 3x the second-highest trace median\n  const secondMax = traceMedians.length >= 2 ? traceMedians[traceMedians.length - 2] : maxTraceMedian;\n  const zoomMax = secondMax * 3;\n\n  const traces = cfg.traces.map(t => ({\n    x: t.x, y: t.y.map(v => v / u.scale), name: t.name,\n    type: 'scatter', mode: t.baseline ? 'lines' : 'lines+markers',\n    line: { color: t.color, width: t.baseline ? 1.5 : 2.5, dash: t.dash || 'solid' },\n    marker: { size: t.baseline ? 0 : 5 },\n    hovertemplate: '%{x} threads: %{y:.4g} ' + u.label + '<extra>%{fullData.name}</extra>',\n  }));\n\n  // Add invisible legend entries for skipped (cannot-complete) libraries\n  const skipped = cfg.skipped_libs || [];\n  for (const sl of skipped) {\n    traces.push({\n      x: [null], y: [null], name: sl.name + ' (CANNOT COMPLETE)',\n      type: 'scatter', mode: 'markers',\n      marker: { size: 12, color: sl.color, symbol: 'x', line: { width: 2, color: sl.color } },\n      hoverinfo: 'name',\n      showlegend: true,\n    });\n  }\n\n  const tl = themeLayout();\n  // Add text annotation when libraries are skipped\n  const annotations = [];\n  if (skipped.length > 0) {\n    const names = skipped.map(s => s.name).join(', ');\n    annotations.push({\n      text: names + ': cannot complete (out of memory)',\n      xref: 'paper', yref: 'paper', x: 0.5, y: -0.12,\n      showarrow: false,\n      font: { size: 11, color: skipped.length === 1 ? skipped[0].color : '#e74c3c' },\n    });\n  }\n  const layout = {\n    ...tl, title: { text: cfg.title + (autoZoom ? ' (auto-zoomed, double-click to reset)' : ''), font: { size: 14 } },\n    xaxis: { ...tl.xaxis, title: cfg.xaxis || 'Threads', fixedrange: true },\n    yaxis: { ...tl.yaxis, title: 'Time (' + u.label + ')', rangemode: 'tozero',\n              ...(autoZoom ? { range: [0, zoomMax] } : {}) },\n    legend: { ...tl.legend, orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1 },\n    margin: { l: 60, r: 20, t: 50, b: skipped.length > 0 ? 70 : 50 }, hovermode: 'x unified',\n    ...(annotations.length > 0 ? { annotations } : {}),\n  };\n  Plotly.newPlot('chart-' + cfg.id, traces, layout, plotlyConfig);\n  pinZeroAxis(cfg.id, 'yaxis');\n}\n\nfunction renderGroupedBarH(cfg) {\n  const allV = cfg.groups.flatMap(g => g.values);\n  const maxV = Math.max(...allV.filter(v => v > 0));\n  const u = autoUnit(maxV);\n  const useLog = cfg.log_scale && maxV / Math.min(...allV.filter(v => v > 0)) > 50;\n  // Reverse so first category is at top\n  const cats = [...cfg.categories].reverse();\n  const traces = cfg.groups.map(g => ({\n    type: 'bar', orientation: 'h', name: g.name,\n    y: cats, x: [...g.values].reverse().map(v => useLog ? v : v / u.scale),\n    marker: { color: g.color, opacity: 0.85 },\n    hovertemplate: useLog\n      ? '%{y}: %{x:.4g} ns<extra>%{fullData.name}</extra>'\n      : '%{y}: %{x:.4g} ' + u.label + '<extra>%{fullData.name}</extra>',\n  }));\n  const tl = themeLayout();\n  const el = document.getElementById('chart-' + cfg.id);\n  if (el) el.style.minHeight = Math.max(350, cfg.categories.length * 40 + 100) + 'px';\n  Plotly.newPlot('chart-' + cfg.id, traces, {\n    ...tl, barmode: 'group', bargap: 0.15, bargroupgap: 0.1,\n    title: { text: cfg.title, font: { size: 14 } },\n    xaxis: { ...tl.xaxis, title: useLog ? 'Time (ns) - log scale' : 'Time (' + u.label + ')',\n              type: useLog ? 'log' : 'linear' },\n    yaxis: { ...tl.yaxis, automargin: true, fixedrange: true },\n    legend: { ...tl.legend, orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1 },\n    margin: { l: 180, r: 20, t: 60, b: 50 },\n  }, plotlyConfig);\n  if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n}\n\nfunction renderGroupedBarV(cfg) {\n  const allV = cfg.groups.flatMap(g => g.values);\n  const maxV = Math.max(...allV.filter(v => v > 0));\n  const u = autoUnit(maxV);\n\n  // Auto-zoom: compare per-group MAX values to detect outlier groups.\n  // Using max (not median) ensures we don't clip the tallest competitive bars.\n  // Exclude error-placeholder values from zoom calculation.\n  const groupMaxes = cfg.groups.map(g => {\n    const errSet = new Set(g.error_indices || []);\n    const pos = g.values.filter((v, i) => v > 0 && !errSet.has(i));\n    return pos.length > 0 ? Math.max(...pos) : 0;\n  }).filter(v => v > 0).sort((a,b) => a - b);\n  const maxGroupMax = groupMaxes.length > 0 ? groupMaxes[groupMaxes.length - 1] : 1;\n  const secondGroupMax = groupMaxes.length >= 2 ? groupMaxes[groupMaxes.length - 2] : maxGroupMax;\n  const autoZoom = groupMaxes.length >= 2 && maxGroupMax / secondGroupMax > 5;\n  const zoomMax = (secondGroupMax * 1.5) / u.scale;\n\n  const traces = cfg.groups.map(g => {\n    const n = g.values.length;\n    const errSet = new Set(g.error_indices || []);\n    const hasErrors = errSet.size > 0;\n\n    // Per-bar colors and patterns for error bars\n    const colors = g.values.map((_, i) => errSet.has(i) ? 'rgba(200,200,200,0.25)' : g.color);\n    const patterns = hasErrors ? {\n      shape: g.values.map((_, i) => errSet.has(i) ? '/' : ''),\n      fgcolor: g.values.map((_, i) => errSet.has(i) ? '#e74c3c' : g.color),\n      solidity: 0.4,\n    } : undefined;\n    // Custom hover: show \"CANNOT COMPLETE\" for error bars\n    const customdata = g.values.map((_, i) => errSet.has(i) ? 'CANNOT COMPLETE' : '');\n    const hovertemplate = g.values.map((_, i) =>\n      errSet.has(i)\n        ? '%{x}: <b>CANNOT COMPLETE</b><extra>' + g.name + '</extra>'\n        : '%{x}: %{y:.4g} ' + u.label + '<extra>' + g.name + '</extra>'\n    );\n\n    return {\n      type: 'bar', name: g.name,\n      x: cfg.categories, y: g.values.map(v => v / u.scale),\n      marker: { color: colors, opacity: 0.85, ...(patterns ? { pattern: patterns } : {}) },\n      customdata, hovertemplate,\n      // Text label inside error bars\n      text: g.values.map((_, i) => errSet.has(i) ? 'CANNOT<br>COMPLETE' : ''),\n      textposition: 'inside', insidetextanchor: 'middle', textangle: -90,\n      textfont: { color: '#e74c3c', size: 11 },\n    };\n  });\n  const tl = themeLayout();\n  Plotly.newPlot('chart-' + cfg.id, traces, {\n    ...tl, barmode: 'group', bargap: 0.2,\n    title: { text: cfg.title + (autoZoom ? ' (auto-zoomed, double-click to reset)' : ''), font: { size: 14 } },\n    xaxis: { ...tl.xaxis, title: cfg.xaxis || '', fixedrange: true },\n    yaxis: { ...tl.yaxis, title: 'Time (' + u.label + ')', rangemode: 'tozero',\n              ...(autoZoom ? { range: [0, zoomMax] } : {}) },\n    legend: { ...tl.legend, title: { text: 'Implementation' } },\n    margin: { l: 60, r: 20, t: 50, b: 50 },\n  }, plotlyConfig);\n  pinZeroAxis(cfg.id, 'yaxis');\n}\n\nfunction renderBarHColored(cfg) {\n  const maxV = Math.max(...cfg.items.map(i => i.time_ns));\n  const minV = Math.min(...cfg.items.filter(i => i.time_ns > 0).map(i => i.time_ns));\n  const u = autoUnit(maxV);\n  const useLog = maxV / minV > 100;\n  // Reverse for top-to-bottom display\n  const items = [...cfg.items].reverse();\n  const trace = {\n    type: 'bar', orientation: 'h',\n    y: items.map(i => i.name), x: items.map(i => useLog ? i.time_ns : i.time_ns / u.scale),\n    marker: { color: items.map(i => i.color), opacity: 0.85 },\n    hovertemplate: useLog\n      ? '%{y}: %{x:.4g} ns<extra></extra>'\n      : '%{y}: %{x:.4g} ' + u.label + '<extra></extra>',\n  };\n  const tl = themeLayout();\n  const el = document.getElementById('chart-' + cfg.id);\n  if (el) el.style.minHeight = Math.max(350, cfg.items.length * 24 + 100) + 'px';\n\n  const layout = {\n    ...tl, showlegend: false,\n    title: { text: cfg.title, font: { size: 14 } },\n    xaxis: { ...tl.xaxis, title: useLog ? 'Time (ns) - log scale' : 'Time (' + u.label + ')',\n              type: useLog ? 'log' : 'linear' },\n    yaxis: { ...tl.yaxis, automargin: true, tickfont: { size: 10 }, fixedrange: true },\n    margin: { l: 250, r: 20, t: 50, b: 50 }, bargap: 0.3,\n  };\n\n  // Add manual legend if provided\n  if (cfg.legend) {\n    layout.showlegend = true;\n    // Add invisible traces for legend\n    const traces = [trace];\n    cfg.legend.forEach(l => {\n      traces.push({\n        type: 'bar', orientation: 'h', x: [null], y: [null],\n        marker: { color: l.color }, name: l.name, showlegend: true,\n      });\n    });\n    trace.showlegend = false;\n    Plotly.newPlot('chart-' + cfg.id, traces, layout, plotlyConfig);\n    if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n    return;\n  }\n  Plotly.newPlot('chart-' + cfg.id, [trace], layout, plotlyConfig);\n  if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n}\n\nfunction renderGroupedBarHError(cfg) {\n  // Reverse for top-to-bottom\n  const cats = [...cfg.categories].reverse();\n  const traces = cfg.groups.map(g => {\n    const vals = [...g.values].reverse();\n    const errs = [...g.errors].reverse();\n    // Clamp lower error bars so they don't go below zero (scheduling error can't be negative)\n    const errMinus = vals.map((v, i) => Math.min(errs[i], v));\n    return {\n      type: 'bar', orientation: 'h', name: g.name,\n      y: cats, x: vals,\n      error_x: { type: 'data', array: errs, arrayminus: errMinus, visible: true },\n      marker: { color: g.color, opacity: 0.85 },\n      hovertemplate: '%{y}: %{x:.2f} +/- %{error_x.array:.2f} us<extra>%{fullData.name}</extra>',\n    };\n  });\n  const tl = themeLayout();\n  Plotly.newPlot('chart-' + cfg.id, traces, {\n    ...tl, barmode: 'group', bargap: 0.2,\n    title: { text: cfg.title, font: { size: 14 } },\n    xaxis: { ...tl.xaxis, title: cfg.xaxis_label || 'Mean Error (us)' },\n    yaxis: { ...tl.yaxis, automargin: true, fixedrange: true },\n    legend: { ...tl.legend },\n    margin: { l: 200, r: 20, t: 50, b: 50 },\n  }, plotlyConfig);\n  pinZeroAxis(cfg.id, 'xaxis');\n}\n\nfunction renderChart(cfg) {\n  switch (cfg.type) {\n    case 'line': renderLine(cfg); break;\n    case 'grouped_bar_h': renderGroupedBarH(cfg); break;\n    case 'grouped_bar_v': renderGroupedBarV(cfg); break;\n    case 'bar_h_colored': renderBarHColored(cfg); break;\n    case 'grouped_bar_h_error': renderGroupedBarHError(cfg); break;\n  }\n}\n\n// ─── Platform switching ────────────────────────────────────────\nfunction buildInfoCards(machine) {\n  const compiler = machine.compiler || {};\n  document.getElementById('infoCards').innerHTML = `\n    <div class=\"info-card\"><div class=\"label\">Platform</div><div class=\"value\">${machine.platform} ${machine.architecture||''}</div><div class=\"detail\">${machine.platform_release||''}</div></div>\n    <div class=\"info-card\"><div class=\"label\">Processor</div><div class=\"value\">${machine.cpu_model}</div><div class=\"detail\">${machine.cpu_cores} cores &middot; ${Math.round(machine.memory_gb||0)} GB RAM</div></div>\n    <div class=\"info-card\"><div class=\"label\">Compiler</div><div class=\"value\">${compiler.compiler_summary||'Unknown'}</div><div class=\"detail\">C++${compiler.cxx_standard||'??'} &middot; ${compiler.build_type||''}</div></div>\n    <div class=\"info-card\"><div class=\"label\">Run Date</div><div class=\"value\">${(machine.timestamp||'').slice(0,10)}</div><div class=\"detail\">${(machine.timestamp||'').slice(11,19)}</div></div>\n  `;\n}\n\nfunction buildSections(charts) {\n  // Group by suite\n  const suites = new Map();\n  charts.forEach(c => {\n    if (!suites.has(c.suite)) suites.set(c.suite, []);\n    suites.get(c.suite).push(c);\n  });\n\n  let html = '';\n  suites.forEach((chartList, suite) => {\n    const display = suite.replace(/_/g, ' ').replace(/\\b\\w/g, l => l.toUpperCase());\n    html += `<section id=\"section-${suite}\" class=\"benchmark-section\"><h2 class=\"section-title\">${display}</h2>`;\n    chartList.forEach(c => {\n      html += `<div class=\"chart-container\"><div id=\"chart-${c.id}\" class=\"chart\"></div></div>`;\n    });\n    html += '</section>';\n  });\n  document.getElementById('chartSections').innerHTML = html;\n}\n\nfunction switchPlatform(idx) {\n  currentPlatformIdx = parseInt(idx);\n  const p = PLATFORMS[currentPlatformIdx];\n  buildInfoCards(p.machine);\n  document.getElementById('statsBar').innerHTML = `\n    <div class=\"stat-item\"><span class=\"stat-dot info\"></span><span>Suites: <strong>${new Set(p.charts.map(c=>c.suite)).size}</strong></span></div>\n    <div class=\"stat-item\"><span class=\"stat-dot ok\"></span><span>Charts: <strong>${p.charts.length}</strong></span></div>\n  `;\n  buildSections(p.charts);\n  // Small delay so DOM is ready\n  requestAnimationFrame(() => {\n    p.charts.forEach(renderChart);\n    observeSections();\n  });\n}\n\nfunction toggleTheme() {\n  currentTheme = currentTheme === 'dark' ? 'light' : 'dark';\n  document.documentElement.setAttribute('data-theme', currentTheme);\n  document.getElementById('themeBtn').textContent = currentTheme === 'dark' ? 'Light' : 'Dark';\n  const p = PLATFORMS[currentPlatformIdx];\n  p.charts.forEach(renderChart);\n}\n\nfunction filterNav(q) {\n  q = q.toLowerCase();\n  document.querySelectorAll('.nav-link').forEach(l => {\n    l.style.display = l.textContent.toLowerCase().includes(q) ? 'block' : 'none';\n  });\n}\n\nlet observer;\nfunction observeSections() {\n  if (observer) observer.disconnect();\n  observer = new IntersectionObserver(entries => {\n    entries.forEach(e => {\n      if (e.isIntersecting) {\n        const id = e.target.id.replace('section-', '');\n        document.querySelectorAll('.nav-link').forEach(l => {\n          l.classList.toggle('active', l.dataset.suite === id);\n        });\n      }\n    });\n  }, { rootMargin: '-20% 0px -70% 0px' });\n  document.querySelectorAll('.benchmark-section').forEach(s => observer.observe(s));\n}\n\n// ─── Init ──────────────────────────────────────────────────────\nconst sel = document.getElementById('platformSelect');\nPLATFORMS.forEach((p, i) => {\n  const opt = document.createElement('option');\n  opt.value = i; opt.textContent = p.label;\n  sel.appendChild(opt);\n});\nswitchPlatform(0);\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/benchmarks/nested_for_details.md",
    "content": "# nested_for - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_serial<kSmallSize> | 5352.63 | ns | 124322 |\n| BM_omp/12/10/real_time | 5377.81 | ns | 131563 |\n| BM_dispenso/1/10/real_time | 5579.38 | ns | 120210 |\n| BM_omp/6/10/real_time | 5747.11 | ns | 103810 |\n| BM_omp/16/10/real_time | 5961.13 | ns | 117578 |\n| BM_omp/8/10/real_time | 6296.00 | ns | 120132 |\n| BM_dispenso/3/10/real_time | 6932.16 | ns | 100625 |\n| BM_dispenso/2/10/real_time | 7243.91 | ns | 95178 |\n| BM_dispenso/4/10/real_time | 7278.11 | ns | 94618 |\n| BM_omp/24/10/real_time | 7365.84 | ns | 94022 |\n| BM_dispenso/8/10/real_time | 7483.65 | ns | 92491 |\n| BM_dispenso/6/10/real_time | 7631.00 | ns | 93758 |\n| BM_omp/4/10/real_time | 7654.10 | ns | 89573 |\n| BM_omp/32/10/real_time | 8834.18 | ns | 77211 |\n| BM_dispenso/12/10/real_time | 9020.92 | ns | 77639 |\n| BM_omp/3/10/real_time | 9420.08 | ns | 72953 |\n| BM_dispenso/16/10/real_time | 10658.85 | ns | 65938 |\n| BM_omp/2/10/real_time | 11625.56 | ns | 60704 |\n| BM_omp/48/10/real_time | 12032.57 | ns | 57350 |\n| BM_dispenso/24/10/real_time | 14324.23 | ns | 48792 |\n| BM_omp/64/10/real_time | 14919.26 | ns | 46589 |\n| BM_dispenso/32/10/real_time | 18650.10 | ns | 35428 |\n| BM_tbb/96/10/real_time | 18809.14 | ns | 37284 |\n| BM_tbb/3/10/real_time | 19017.57 | ns | 37765 |\n| BM_tbb/4/10/real_time | 19058.76 | ns | 36556 |\n| BM_tbb/1/10/real_time | 19188.71 | ns | 36652 |\n| BM_tbb/64/10/real_time | 19429.99 | ns | 35493 |\n| BM_tbb/2/10/real_time | 19506.36 | ns | 36747 |\n| BM_tbb/48/10/real_time | 20006.65 | ns | 34731 |\n| BM_tbb/6/10/real_time | 20286.73 | ns | 35173 |\n| BM_omp/1/10/real_time | 20393.95 | ns | 35299 |\n| BM_omp/96/10/real_time | 20662.79 | ns | 33749 |\n| BM_tbb/8/10/real_time | 20791.68 | ns | 33283 |\n| BM_tbb/32/10/real_time | 20957.43 | ns | 33327 |\n| BM_tbb/128/10/real_time | 20960.13 | ns | 33167 |\n| BM_tbb/24/10/real_time | 21658.25 | ns | 31842 |\n| BM_tbb/16/10/real_time | 21702.85 | ns | 31734 |\n| BM_dispenso/48/10/real_time | 21774.12 | ns | 31082 |\n| BM_tbb/12/10/real_time | 21936.70 | ns | 31931 |\n| BM_dispenso/64/10/real_time | 22319.99 | ns | 31634 |\n| BM_dispenso/96/10/real_time | 23406.57 | ns | 30318 |\n| BM_dispenso/192/10/real_time | 23604.61 | ns | 29430 |\n| BM_tbb/192/10/real_time | 24463.64 | ns | 33165 |\n| BM_dispenso/128/10/real_time | 24901.25 | ns | 27826 |\n| BM_omp/128/10/real_time | 26679.71 | ns | 26129 |\n| BM_omp/192/10/real_time | 273944.86 | ns | 10000 |\n| BM_omp/128/500/real_time | 312656.55 | ns | 2215 |\n| BM_omp/64/500/real_time | 329473.09 | ns | 2006 |\n| BM_omp/96/500/real_time | 401461.99 | ns | 1725 |\n| BM_dispenso/128/500/real_time | 438805.14 | ns | 1227 |\n| BM_dispenso/96/500/real_time | 441404.08 | ns | 1588 |\n| BM_dispenso/64/500/real_time | 481504.03 | ns | 1070 |\n| BM_omp/48/500/real_time | 494762.83 | ns | 1382 |\n| BM_dispenso/48/500/real_time | 498748.72 | ns | 1167 |\n| BM_dispenso/192/500/real_time | 518038.24 | ns | 1167 |\n| BM_omp/32/500/real_time | 610597.69 | ns | 910 |\n| BM_tbb/128/500/real_time | 640218.21 | ns | 981 |\n| BM_tbb/96/500/real_time | 694327.70 | ns | 891 |\n| BM_tbb/192/500/real_time | 714523.30 | ns | 894 |\n| BM_omp/24/500/real_time | 723348.28 | ns | 978 |\n| BM_dispenso/32/500/real_time | 830442.81 | ns | 648 |\n| BM_tbb/64/500/real_time | 830623.84 | ns | 768 |\n| BM_tbb/48/500/real_time | 950325.79 | ns | 632 |\n| BM_dispenso/24/500/real_time | 987603.23 | ns | 599 |\n| BM_omp/16/500/real_time | 1125305.58 | ns | 502 |\n| BM_dispenso/16/500/real_time | 1142851.99 | ns | 507 |\n| BM_tbb/32/500/real_time | 1274326.51 | ns | 503 |\n| BM_dispenso/12/500/real_time | 1429623.97 | ns | 396 |\n| BM_omp/12/500/real_time | 1461195.16 | ns | 387 |\n| BM_tbb/24/500/real_time | 1604574.71 | ns | 391 |\n| BM_dispenso/8/500/real_time | 2132988.67 | ns | 270 |\n| BM_omp/8/500/real_time | 2241676.03 | ns | 268 |\n| BM_tbb/16/500/real_time | 2410862.28 | ns | 263 |\n| BM_dispenso/6/500/real_time | 2925520.60 | ns | 198 |\n| BM_omp/6/500/real_time | 3009802.99 | ns | 194 |\n| BM_tbb/12/500/real_time | 3094319.97 | ns | 214 |\n| BM_dispenso/4/500/real_time | 4538486.45 | ns | 126 |\n| BM_tbb/8/500/real_time | 4703940.40 | ns | 137 |\n| BM_omp/4/500/real_time | 4790064.82 | ns | 119 |\n| BM_omp/192/500/real_time | 5076339.11 | ns | 1480 |\n| BM_tbb/6/500/real_time | 6423339.10 | ns | 99 |\n| BM_dispenso/3/500/real_time | 6511763.34 | ns | 86 |\n| BM_omp/3/500/real_time | 6763734.10 | ns | 83 |\n| BM_tbb/4/500/real_time | 10046958.05 | ns | 64 |\n| BM_dispenso/2/500/real_time | 11740972.65 | ns | 46 |\n| BM_omp/2/500/real_time | 12219473.80 | ns | 46 |\n| BM_tbb/3/500/real_time | 14323577.03 | ns | 44 |\n| BM_tbb/2/500/real_time | 26588207.11 | ns | 21 |\n| BM_tbb/192/3000/real_time | 28897564.29 | ns | 23 |\n| BM_omp/128/3000/real_time | 33274534.62 | ns | 20 |\n| BM_dispenso/128/3000/real_time | 34937168.23 | ns | 19 |\n| BM_dispenso/192/3000/real_time | 36824789.98 | ns | 19 |\n| BM_tbb/128/3000/real_time | 37577435.58 | ns | 18 |\n| BM_omp/192/3000/real_time | 39880230.69 | ns | 17 |\n| BM_omp/96/3000/real_time | 41533113.18 | ns | 17 |\n| BM_dispenso/96/3000/real_time | 42337563.61 | ns | 13 |\n| BM_serial<kMediumSize> | 44446194.08 | ns | 12 |\n| BM_tbb/96/3000/real_time | 45465328.79 | ns | 15 |\n| BM_dispenso/1/500/real_time | 46926374.80 | ns | 11 |\n| BM_omp/1/500/real_time | 48987052.15 | ns | 11 |\n| BM_omp/64/3000/real_time | 53292871.45 | ns | 12 |\n| BM_dispenso/64/3000/real_time | 54803768.17 | ns | 12 |\n| BM_tbb/64/3000/real_time | 60580727.56 | ns | 11 |\n| BM_tbb/1/500/real_time | 66736426.20 | ns | 9 |\n| BM_omp/48/3000/real_time | 67082724.72 | ns | 10 |\n| BM_dispenso/48/3000/real_time | 68203550.66 | ns | 9 |\n| BM_tbb/48/3000/real_time | 78102464.89 | ns | 9 |\n| BM_omp/32/3000/real_time | 96375407.38 | ns | 7 |\n| BM_dispenso/32/3000/real_time | 97165372.49 | ns | 7 |\n| BM_tbb/32/3000/real_time | 109506090.17 | ns | 6 |\n| BM_omp/24/3000/real_time | 128551444.41 | ns | 5 |\n| BM_dispenso/24/3000/real_time | 130408811.20 | ns | 5 |\n| BM_tbb/24/3000/real_time | 145830169.69 | ns | 5 |\n| BM_omp/16/3000/real_time | 194345360.16 | ns | 4 |\n| BM_dispenso/16/3000/real_time | 203846107.55 | ns | 3 |\n| BM_tbb/16/3000/real_time | 220621350.53 | ns | 3 |\n| BM_omp/12/3000/real_time | 259661081.56 | ns | 3 |\n| BM_dispenso/12/3000/real_time | 267909605.06 | ns | 3 |\n| BM_tbb/12/3000/real_time | 294873585.92 | ns | 2 |\n| BM_dispenso/8/3000/real_time | 389330674.89 | ns | 2 |\n| BM_omp/8/3000/real_time | 389388010.84 | ns | 2 |\n| BM_tbb/8/3000/real_time | 440575836.23 | ns | 2 |\n| BM_dispenso/6/3000/real_time | 517882110.55 | ns | 1 |\n| BM_omp/6/3000/real_time | 519871765.75 | ns | 1 |\n| BM_tbb/6/3000/real_time | 582667542.62 | ns | 1 |\n| BM_dispenso/4/3000/real_time | 754384193.57 | ns | 1 |\n| BM_omp/4/3000/real_time | 758184684.44 | ns | 1 |\n| BM_tbb/4/3000/real_time | 850331416.35 | ns | 1 |\n| BM_dispenso/3/3000/real_time | 985554648.56 | ns | 1 |\n| BM_omp/3/3000/real_time | 990451890.98 | ns | 1 |\n| BM_tbb/3/3000/real_time | 1120893433.69 | ns | 1 |\n| BM_dispenso/2/3000/real_time | 1451981129.12 | ns | 1 |\n| BM_omp/2/3000/real_time | 1476024180.65 | ns | 1 |\n| BM_tbb/2/3000/real_time | 1654469324.28 | ns | 1 |\n| BM_dispenso/1/3000/real_time | 2908631879.84 | ns | 1 |\n| BM_serial<kLargeSize> | 2934453791.01 | ns | 1 |\n| BM_omp/1/3000/real_time | 2975622540.34 | ns | 1 |\n| BM_tbb/1/3000/real_time | 3314157780.26 | ns | 1 |\n"
  },
  {
    "path": "docs/benchmarks/nested_pool_details.md",
    "content": "# nested_pool - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_folly/128/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/12/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/8/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/24/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/32/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/48/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/64/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/96/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/6/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/192/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/16/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/1/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/3/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/4/1000000/real_time | 0.00 | us | 1 |\n| BM_folly/2/1000000/real_time | 0.00 | us | 1 |\n| BM_dispenso/6/1000/real_time | 325.99 | us | 1955 |\n| BM_dispenso/1/1000/real_time | 343.19 | us | 1986 |\n| BM_dispenso/4/1000/real_time | 349.33 | us | 1887 |\n| BM_dispenso/2/1000/real_time | 425.45 | us | 1661 |\n| BM_dispenso/3/1000/real_time | 450.04 | us | 1677 |\n| BM_tbb/6/1000/real_time | 500.96 | us | 1192 |\n| BM_tbb/12/1000/real_time | 510.32 | us | 1000 |\n| BM_tbb/8/1000/real_time | 518.89 | us | 1434 |\n| BM_tbb/16/1000/real_time | 528.18 | us | 1261 |\n| BM_tbb/4/1000/real_time | 530.08 | us | 1286 |\n| BM_dispenso/8/1000/real_time | 545.19 | us | 1196 |\n| BM_tbb/24/1000/real_time | 581.87 | us | 1173 |\n| BM_tbb/3/1000/real_time | 615.71 | us | 1165 |\n| BM_tbb/32/1000/real_time | 618.90 | us | 1114 |\n| BM_tbb/2/1000/real_time | 649.29 | us | 1036 |\n| BM_tbb/1/1000/real_time | 815.86 | us | 828 |\n| BM_tbb/48/1000/real_time | 932.62 | us | 685 |\n| BM_dispenso/12/1000/real_time | 1217.06 | us | 576 |\n| BM_tbb/64/1000/real_time | 1298.58 | us | 532 |\n| BM_dispenso/16/1000/real_time | 1367.10 | us | 458 |\n| BM_tbb/96/1000/real_time | 1899.00 | us | 369 |\n| BM_tbb/128/1000/real_time | 2205.34 | us | 317 |\n| BM_tbb/192/1000/real_time | 2342.31 | us | 295 |\n| BM_dispenso/24/1000/real_time | 2673.69 | us | 247 |\n| BM_dispenso/6/10000/real_time | 3673.71 | us | 205 |\n| BM_dispenso/32/1000/real_time | 3797.78 | us | 342 |\n| BM_folly/128/1000/real_time | 4447.42 | us | 131 |\n| BM_folly/192/1000/real_time | 4498.94 | us | 125 |\n| BM_folly/96/1000/real_time | 4502.18 | us | 135 |\n| BM_dispenso/4/10000/real_time | 4587.68 | us | 132 |\n| BM_folly/64/1000/real_time | 4879.30 | us | 136 |\n| BM_dispenso/48/1000/real_time | 5085.74 | us | 100 |\n| BM_dispenso/8/10000/real_time | 5252.31 | us | 100 |\n| BM_folly/48/1000/real_time | 5343.84 | us | 122 |\n| BM_dispenso/64/1000/real_time | 5776.43 | us | 111 |\n| BM_dispenso/3/10000/real_time | 6146.50 | us | 115 |\n| BM_folly/32/1000/real_time | 6218.64 | us | 107 |\n| BM_dispenso/128/1000/real_time | 6266.09 | us | 112 |\n| BM_dispenso/192/1000/real_time | 6391.82 | us | 111 |\n| BM_dispenso/96/1000/real_time | 7058.88 | us | 95 |\n| BM_folly/24/1000/real_time | 7076.47 | us | 92 |\n| BM_folly/6/1000/real_time | 8715.42 | us | 92 |\n| BM_folly/16/1000/real_time | 8834.35 | us | 76 |\n| BM_dispenso/12/10000/real_time | 8948.02 | us | 72 |\n| BM_tbb/96/10000/real_time | 9193.33 | us | 74 |\n| BM_folly/4/1000/real_time | 9512.76 | us | 72 |\n| BM_folly/12/1000/real_time | 9973.22 | us | 64 |\n| BM_folly/8/1000/real_time | 10355.91 | us | 51 |\n| BM_dispenso/2/10000/real_time | 10521.48 | us | 64 |\n| BM_dispenso/1/10000/real_time | 10539.84 | us | 64 |\n| BM_tbb/64/10000/real_time | 11189.42 | us | 63 |\n| BM_folly/1/1000/real_time | 12064.76 | us | 49 |\n| BM_folly/3/1000/real_time | 12517.39 | us | 56 |\n| BM_tbb/48/10000/real_time | 13262.26 | us | 53 |\n| BM_dispenso/24/10000/real_time | 13670.78 | us | 38 |\n| BM_dispenso/16/10000/real_time | 13690.36 | us | 56 |\n| BM_folly/2/1000/real_time | 14950.34 | us | 48 |\n| BM_tbb/128/10000/real_time | 15952.46 | us | 42 |\n| BM_dispenso/32/10000/real_time | 16237.09 | us | 41 |\n| BM_tbb/32/10000/real_time | 17077.00 | us | 41 |\n| BM_tbb/24/10000/real_time | 20117.07 | us | 35 |\n| BM_tbb/8/10000/real_time | 24390.80 | us | 28 |\n| BM_tbb/16/10000/real_time | 24553.90 | us | 29 |\n| BM_tbb/192/10000/real_time | 24581.74 | us | 29 |\n| BM_tbb/3/10000/real_time | 24656.19 | us | 28 |\n| BM_tbb/6/10000/real_time | 24867.49 | us | 29 |\n| BM_tbb/4/10000/real_time | 24964.61 | us | 28 |\n| BM_tbb/2/10000/real_time | 25459.13 | us | 27 |\n| BM_tbb/1/10000/real_time | 25880.37 | us | 28 |\n| BM_tbb/12/10000/real_time | 26109.60 | us | 26 |\n| BM_dispenso/48/10000/real_time | 47591.21 | us | 14 |\n| BM_dispenso/64/10000/real_time | 58463.12 | us | 12 |\n| BM_dispenso/96/10000/real_time | 64178.89 | us | 10 |\n| BM_dispenso/128/10000/real_time | 72989.45 | us | 10 |\n| BM_dispenso/192/10000/real_time | 79560.49 | us | 8 |\n| BM_folly/192/10000/real_time | 106249.63 | us | 6 |\n| BM_folly/128/10000/real_time | 112009.02 | us | 6 |\n| BM_folly/96/10000/real_time | 123839.03 | us | 6 |\n| BM_folly/64/10000/real_time | 128345.12 | us | 5 |\n| BM_folly/48/10000/real_time | 141985.48 | us | 5 |\n| BM_folly/32/10000/real_time | 166693.36 | us | 4 |\n| BM_folly/24/10000/real_time | 191060.68 | us | 4 |\n| BM_folly/16/10000/real_time | 226489.17 | us | 3 |\n| BM_folly/12/10000/real_time | 254656.73 | us | 2 |\n| BM_folly/8/10000/real_time | 283280.30 | us | 2 |\n| BM_folly/6/10000/real_time | 295460.53 | us | 3 |\n| BM_folly/4/10000/real_time | 306877.08 | us | 2 |\n| BM_folly/3/10000/real_time | 364927.17 | us | 2 |\n| BM_folly/2/10000/real_time | 664485.05 | us | 1 |\n| BM_dispenso/64/1000000/real_time | 778425.68 | us | 1 |\n| BM_dispenso/48/1000000/real_time | 847233.67 | us | 1 |\n| BM_dispenso/32/1000000/real_time | 947500.57 | us | 1 |\n| BM_dispenso/24/1000000/real_time | 983596.96 | us | 1 |\n| BM_folly/1/10000/real_time | 983616.49 | us | 1 |\n| BM_tbb/192/1000000/real_time | 1358241.92 | us | 1 |\n| BM_tbb/128/1000000/real_time | 1444985.21 | us | 1 |\n| BM_tbb/96/1000000/real_time | 1597546.47 | us | 1 |\n| BM_tbb/64/1000000/real_time | 1993163.84 | us | 1 |\n| BM_dispenso/16/1000000/real_time | 2024024.62 | us | 1 |\n| BM_dispenso/8/1000000/real_time | 2106747.59 | us | 1 |\n| BM_dispenso/12/1000000/real_time | 2119761.85 | us | 1 |\n| BM_dispenso/6/1000000/real_time | 2285997.51 | us | 1 |\n| BM_tbb/48/1000000/real_time | 2449716.77 | us | 1 |\n| BM_dispenso/4/1000000/real_time | 3027219.49 | us | 1 |\n| BM_dispenso/2/1000000/real_time | 3159682.06 | us | 1 |\n| BM_dispenso/3/1000000/real_time | 3348506.64 | us | 1 |\n| BM_tbb/32/1000000/real_time | 3429660.21 | us | 1 |\n| BM_tbb/24/1000000/real_time | 4332955.20 | us | 1 |\n| BM_dispenso/96/1000000/real_time | 4406276.82 | us | 1 |\n| BM_dispenso/128/1000000/real_time | 5219742.50 | us | 1 |\n| BM_tbb/16/1000000/real_time | 6071265.79 | us | 1 |\n| BM_tbb/12/1000000/real_time | 7583535.18 | us | 1 |\n| BM_dispenso/192/1000000/real_time | 8143889.19 | us | 1 |\n| BM_tbb/8/1000000/real_time | 10309799.41 | us | 1 |\n| BM_dispenso/1/1000000/real_time | 10333296.42 | us | 1 |\n| BM_tbb/6/1000000/real_time | 12545453.25 | us | 1 |\n| BM_tbb/4/1000000/real_time | 15950276.53 | us | 1 |\n| BM_tbb/3/1000000/real_time | 18490876.57 | us | 1 |\n| BM_tbb/2/1000000/real_time | 21539772.28 | us | 1 |\n| BM_tbb/1/1000000/real_time | 25233722.73 | us | 1 |\n"
  },
  {
    "path": "docs/benchmarks/once_function_details.md",
    "content": "# once_function - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_move_once_function<kLargeSize> | 13.29 | ns | 54440054 |\n| BM_move_once_function<kSmallSize> | 17.13 | ns | 40441071 |\n| BM_move_once_function<kMediumSize> | 18.02 | ns | 38857001 |\n| BM_move_once_function<kExtraLargeSize> | 33.54 | ns | 21383979 |\n| BM_move_std_function<kMediumSize> | 90.97 | ns | 7756973 |\n| BM_move_std_function<kSmallSize> | 91.09 | ns | 7710676 |\n| BM_move_std_function<kLargeSize> | 94.42 | ns | 7299053 |\n| BM_move_std_function<kExtraLargeSize> | 105.35 | ns | 6775091 |\n| BM_queue_inline_function<kSmallSize> | 1041.31 | ns | 707357 |\n| BM_queue_inline_function<kMediumSize> | 1862.85 | ns | 387990 |\n| BM_queue_once_function<kSmallSize> | 2739.51 | ns | 260781 |\n| BM_queue_once_function<kMediumSize> | 3002.41 | ns | 234757 |\n| BM_queue_inline_function<kLargeSize> | 3094.38 | ns | 220748 |\n| BM_queue_std_function<kSmallSize> | 3411.29 | ns | 210644 |\n| BM_queue_once_function<kLargeSize> | 3546.94 | ns | 201507 |\n| BM_queue_std_function<kMediumSize> | 3713.12 | ns | 200697 |\n| BM_queue_std_function<kLargeSize> | 4922.03 | ns | 147424 |\n| BM_queue_std_function<kExtraLargeSize> | 6862.80 | ns | 105556 |\n| BM_queue_inline_function<kExtraLargeSize> | 9352.52 | ns | 72910 |\n| BM_queue_once_function<kExtraLargeSize> | 58445.14 | ns | 12402 |\n"
  },
  {
    "path": "docs/benchmarks/pipeline_details.md",
    "content": "# pipeline - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso_par/real_time | 4155179.07 | ns | 170 |\n| BM_tbb_par/real_time | 4367384.58 | ns | 162 |\n| BM_taskflow_par/real_time | 69190848.06 | ns | 10 |\n| BM_taskflow/real_time | 117103163.15 | ns | 6 |\n| BM_tbb/real_time | 148514535.65 | ns | 5 |\n| BM_dispenso/real_time | 156323259.70 | ns | 5 |\n| BM_serial/real_time | 196434217.19 | ns | 3 |\n"
  },
  {
    "path": "docs/benchmarks/pool_allocator_details.md",
    "content": "# pool_allocator - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_nl_pool_allocator_arena<kLargeSize>/8192 | 17054.11 | ns | 40406 |\n| BM_nl_pool_allocator_arena<kSmallSize>/8192 | 17333.79 | ns | 40170 |\n| BM_nl_pool_allocator_arena<kMediumSize>/8192 | 17700.59 | ns | 40797 |\n| BM_pool_allocator_arena<kSmallSize>/8192 | 21821.18 | ns | 32799 |\n| BM_pool_allocator_arena<kLargeSize>/8192 | 22647.31 | ns | 30430 |\n| BM_pool_allocator_arena<kMediumSize>/8192 | 22684.09 | ns | 30118 |\n| BM_nl_pool_allocator<kLargeSize>/8192 | 29741.05 | ns | 23588 |\n| BM_nl_pool_allocator<kMediumSize>/8192 | 31655.55 | ns | 22052 |\n| BM_nl_pool_allocator<kSmallSize>/8192 | 34342.47 | ns | 21522 |\n| BM_pool_allocator<kLargeSize>/8192 | 36484.57 | ns | 19186 |\n| BM_pool_allocator<kMediumSize>/8192 | 37425.53 | ns | 17877 |\n| BM_pool_allocator<kSmallSize>/8192 | 37987.55 | ns | 17682 |\n| BM_nl_pool_allocator_arena<kLargeSize>/32768 | 69236.58 | ns | 9925 |\n| BM_nl_pool_allocator_arena<kSmallSize>/32768 | 69912.30 | ns | 9944 |\n| BM_nl_pool_allocator_arena<kMediumSize>/32768 | 70310.29 | ns | 9919 |\n| BM_pool_allocator_arena<kLargeSize>/32768 | 89909.23 | ns | 7441 |\n| BM_pool_allocator_arena<kMediumSize>/32768 | 90412.18 | ns | 7427 |\n| BM_pool_allocator_arena<kSmallSize>/32768 | 90838.42 | ns | 7757 |\n| BM_nl_pool_allocator<kLargeSize>/32768 | 120847.58 | ns | 5878 |\n| BM_pool_allocator_threaded<kLargeSize,2>/8192 | 121028.54 | ns | 5910 |\n| BM_pool_allocator_threaded<kSmallSize,2>/8192 | 121729.99 | ns | 5509 |\n| BM_nl_pool_allocator<kMediumSize>/32768 | 127654.59 | ns | 5519 |\n| BM_pool_allocator_threaded<kMediumSize,2>/8192 | 129158.18 | ns | 5764 |\n| BM_nl_pool_allocator<kSmallSize>/32768 | 137988.98 | ns | 5153 |\n| BM_pool_allocator<kLargeSize>/32768 | 144693.54 | ns | 4707 |\n| BM_pool_allocator<kSmallSize>/32768 | 152049.96 | ns | 4655 |\n| BM_pool_allocator<kMediumSize>/32768 | 154021.98 | ns | 4401 |\n| BM_pool_allocator_threaded<kMediumSize,2>/32768 | 503743.12 | ns | 1228 |\n| BM_pool_allocator_threaded<kSmallSize,2>/32768 | 506220.02 | ns | 1000 |\n| BM_pool_allocator_threaded<kLargeSize,2>/32768 | 531615.33 | ns | 1363 |\n| BM_pool_allocator_threaded<kLargeSize,8>/8192 | 1621277.61 | ns | 345 |\n| BM_pool_allocator_threaded<kSmallSize,8>/8192 | 1680099.48 | ns | 402 |\n| BM_pool_allocator_threaded<kMediumSize,8>/8192 | 1788910.60 | ns | 544 |\n| BM_mallocfree_threaded<kSmallSize,2>/8192 | 3233608.82 | ns | 216 |\n| BM_mallocfree<kSmallSize>/8192 | 3248480.53 | ns | 242 |\n| BM_mallocfree_threaded<kSmallSize,16>/8192 | 4259915.39 | ns | 164 |\n| BM_mallocfree_threaded<kSmallSize,8>/8192 | 4446897.58 | ns | 139 |\n| BM_pool_allocator_threaded<kMediumSize,8>/32768 | 7479885.65 | ns | 71 |\n| BM_pool_allocator_threaded<kLargeSize,8>/32768 | 8125131.46 | ns | 88 |\n| BM_pool_allocator_threaded<kSmallSize,8>/32768 | 8341532.25 | ns | 81 |\n| BM_mallocfree<kMediumSize>/8192 | 13392285.97 | ns | 55 |\n| BM_mallocfree<kSmallSize>/32768 | 13861253.50 | ns | 52 |\n| BM_mallocfree_threaded<kMediumSize,2>/8192 | 14138992.68 | ns | 48 |\n| BM_mallocfree_threaded<kMediumSize,8>/8192 | 14603246.74 | ns | 48 |\n| BM_mallocfree_threaded<kSmallSize,2>/32768 | 15468932.77 | ns | 44 |\n| BM_mallocfree_threaded<kMediumSize,16>/8192 | 15805052.22 | ns | 45 |\n| BM_mallocfree<kLargeSize>/8192 | 17367546.67 | ns | 42 |\n| BM_mallocfree_threaded<kSmallSize,8>/32768 | 17502973.00 | ns | 38 |\n| BM_mallocfree_threaded<kSmallSize,16>/32768 | 17979591.92 | ns | 34 |\n| BM_mallocfree_threaded<kLargeSize,2>/8192 | 18603123.63 | ns | 40 |\n| BM_pool_allocator_threaded<kLargeSize,16>/8192 | 22322069.69 | ns | 34 |\n| BM_pool_allocator_threaded<kMediumSize,16>/8192 | 24341023.80 | ns | 34 |\n| BM_pool_allocator_threaded<kSmallSize,16>/8192 | 27201183.49 | ns | 43 |\n| BM_mallocfree_threaded<kLargeSize,8>/8192 | 37882218.23 | ns | 21 |\n| BM_mallocfree_threaded<kMediumSize,8>/32768 | 52349818.25 | ns | 12 |\n| BM_mallocfree_threaded<kMediumSize,2>/32768 | 56055353.80 | ns | 12 |\n| BM_mallocfree<kMediumSize>/32768 | 57522366.16 | ns | 11 |\n| BM_mallocfree_threaded<kMediumSize,16>/32768 | 60005804.71 | ns | 10 |\n| BM_mallocfree<kLargeSize>/32768 | 73372758.92 | ns | 10 |\n| BM_mallocfree_threaded<kLargeSize,2>/32768 | 101322307.38 | ns | 7 |\n| BM_mallocfree_threaded<kLargeSize,16>/8192 | 102502740.30 | ns | 6 |\n| BM_pool_allocator_threaded<kSmallSize,16>/32768 | 135514692.96 | ns | 5 |\n| BM_pool_allocator_threaded<kMediumSize,16>/32768 | 157790044.79 | ns | 4 |\n| BM_pool_allocator_threaded<kLargeSize,16>/32768 | 196176297.03 | ns | 4 |\n| BM_mallocfree_threaded<kLargeSize,8>/32768 | 343516790.00 | ns | 3 |\n| BM_mallocfree_threaded<kLargeSize,16>/32768 | 937468832.36 | ns | 1 |\n"
  },
  {
    "path": "docs/benchmarks/rw_lock_details.md",
    "content": "# rw_lock - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_serial<NopMutex>/512/real_time | 234541.82 | ns | 3096 |\n| BM_serial<NopMutex>/2/real_time | 297997.41 | ns | 2336 |\n| BM_serial<NopMutex>/8/real_time | 305736.59 | ns | 2221 |\n| BM_serial<NopMutex>/128/real_time | 308857.05 | ns | 2328 |\n| BM_serial<NopMutex>/32/real_time | 346415.75 | ns | 2367 |\n| BM_serial<dispenso::RWLock>/512/real_time | 3401847.25 | ns | 203 |\n| BM_serial<dispenso::RWLock>/32/real_time | 3413924.16 | ns | 199 |\n| BM_serial<dispenso::RWLock>/128/real_time | 3415086.27 | ns | 202 |\n| BM_serial<dispenso::RWLock>/8/real_time | 3443533.27 | ns | 202 |\n| BM_serial<dispenso::RWLock>/2/real_time | 3493863.55 | ns | 199 |\n| BM_parallel<dispenso::RWLock>/1/8/real_time | 3593337.65 | ns | 188 |\n| BM_parallel<dispenso::RWLock>/1/512/real_time | 3641967.67 | ns | 196 |\n| BM_parallel<dispenso::RWLock>/1/2/real_time | 3675817.93 | ns | 189 |\n| BM_parallel<dispenso::RWLock>/1/32/real_time | 3693638.57 | ns | 190 |\n| BM_parallel<dispenso::RWLock>/1/128/real_time | 3696675.29 | ns | 194 |\n| BM_serial<std::shared_mutex>/512/real_time | 4977050.46 | ns | 141 |\n| BM_parallel<std::shared_mutex>/1/128/real_time | 5030428.58 | ns | 137 |\n| BM_parallel<std::shared_mutex>/1/512/real_time | 5100608.31 | ns | 135 |\n| BM_serial<std::shared_mutex>/128/real_time | 5174942.85 | ns | 128 |\n| BM_serial<std::shared_mutex>/32/real_time | 5192198.83 | ns | 133 |\n| BM_parallel<std::shared_mutex>/1/32/real_time | 5305408.82 | ns | 134 |\n| BM_serial<std::shared_mutex>/8/real_time | 5455984.98 | ns | 128 |\n| BM_parallel<std::shared_mutex>/1/8/real_time | 5694363.33 | ns | 122 |\n| BM_serial<std::shared_mutex>/2/real_time | 6761902.37 | ns | 104 |\n| BM_parallel<std::shared_mutex>/1/2/real_time | 7094738.37 | ns | 97 |\n| BM_parallel<dispenso::RWLock>/2/512/real_time | 15736565.84 | ns | 46 |\n| BM_parallel<dispenso::RWLock>/2/128/real_time | 16582068.77 | ns | 42 |\n| BM_parallel<dispenso::RWLock>/2/32/real_time | 19130194.77 | ns | 35 |\n| BM_parallel<dispenso::RWLock>/2/8/real_time | 27984743.47 | ns | 24 |\n| BM_parallel<dispenso::RWLock>/4/512/real_time | 35404025.95 | ns | 20 |\n| BM_parallel<dispenso::RWLock>/4/128/real_time | 39269209.43 | ns | 18 |\n| BM_parallel<dispenso::RWLock>/2/2/real_time | 44925847.21 | ns | 16 |\n| BM_parallel<std::shared_mutex>/2/512/real_time | 48039350.16 | ns | 15 |\n| BM_parallel<dispenso::RWLock>/4/32/real_time | 57459885.83 | ns | 13 |\n| BM_parallel<std::shared_mutex>/2/128/real_time | 68098193.71 | ns | 11 |\n| BM_parallel<std::shared_mutex>/2/2/real_time | 75076002.26 | ns | 10 |\n| BM_parallel<std::shared_mutex>/4/512/real_time | 78770878.83 | ns | 9 |\n| BM_parallel<dispenso::RWLock>/8/512/real_time | 80790802.42 | ns | 9 |\n| BM_parallel<std::shared_mutex>/2/32/real_time | 82806976.93 | ns | 9 |\n| BM_parallel<std::shared_mutex>/2/8/real_time | 95574075.82 | ns | 8 |\n| BM_parallel<dispenso::RWLock>/8/128/real_time | 99372046.87 | ns | 7 |\n| BM_parallel<dispenso::RWLock>/4/8/real_time | 109256845.90 | ns | 6 |\n| BM_parallel<dispenso::RWLock>/4/2/real_time | 146843415.13 | ns | 5 |\n| BM_parallel<std::shared_mutex>/4/2/real_time | 171788787.93 | ns | 4 |\n| BM_parallel<dispenso::RWLock>/8/32/real_time | 175050012.30 | ns | 4 |\n| BM_parallel<std::shared_mutex>/4/128/real_time | 202781901.23 | ns | 4 |\n| BM_parallel<dispenso::RWLock>/16/512/real_time | 227628373.23 | ns | 3 |\n| BM_parallel<std::shared_mutex>/8/512/real_time | 244290089.23 | ns | 3 |\n| BM_parallel<std::shared_mutex>/4/8/real_time | 293520961.89 | ns | 2 |\n| BM_parallel<dispenso::RWLock>/16/128/real_time | 344752916.13 | ns | 2 |\n| BM_parallel<std::shared_mutex>/8/2/real_time | 359693103.47 | ns | 2 |\n| BM_parallel<dispenso::RWLock>/8/8/real_time | 363515906.04 | ns | 2 |\n| BM_parallel<std::shared_mutex>/4/32/real_time | 366221060.98 | ns | 2 |\n| BM_parallel<std::shared_mutex>/8/128/real_time | 421815840.53 | ns | 2 |\n| BM_parallel<dispenso::RWLock>/32/512/real_time | 497091038.15 | ns | 2 |\n| BM_parallel<std::shared_mutex>/16/512/real_time | 506448486.82 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/8/2/real_time | 512869147.58 | ns | 2 |\n| BM_parallel<std::shared_mutex>/8/8/real_time | 623631633.82 | ns | 1 |\n| BM_parallel<std::shared_mutex>/16/2/real_time | 697507264.09 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/16/32/real_time | 708006797.36 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/32/128/real_time | 889477882.53 | ns | 1 |\n| BM_parallel<std::shared_mutex>/8/32/real_time | 897052172.57 | ns | 1 |\n| BM_parallel<std::shared_mutex>/32/512/real_time | 976485032.59 | ns | 1 |\n| BM_parallel<std::shared_mutex>/16/128/real_time | 1047838592.90 | ns | 1 |\n| BM_parallel<std::shared_mutex>/16/8/real_time | 1180674405.77 | ns | 1 |\n| BM_parallel<std::shared_mutex>/32/2/real_time | 1345944730.56 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/16/8/real_time | 1736350167.54 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/32/32/real_time | 2051244040.95 | ns | 1 |\n| BM_parallel<std::shared_mutex>/16/32/real_time | 2053894903.51 | ns | 1 |\n| BM_parallel<std::shared_mutex>/32/128/real_time | 2159483877.94 | ns | 1 |\n| BM_parallel<std::shared_mutex>/32/8/real_time | 2524126691.74 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/16/2/real_time | 2890445239.84 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/32/8/real_time | 3840729236.60 | ns | 1 |\n| BM_parallel<std::shared_mutex>/32/32/real_time | 4473716894.16 | ns | 1 |\n| BM_parallel<dispenso::RWLock>/32/2/real_time | 10992805242.54 | ns | 1 |\n"
  },
  {
    "path": "docs/benchmarks/simple_for_details.md",
    "content": "# simple_for - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_serial<kSmallSize> | 137.00 | ns | 5252614 |\n| BM_dispenso_static_chunk/1/1000/real_time | 141.49 | ns | 4960331 |\n| BM_dispenso_auto_chunk/12/1000/real_time | 141.53 | ns | 4813582 |\n| BM_dispenso_static_chunk/8/1000/real_time | 142.09 | ns | 4652275 |\n| BM_dispenso_static_chunk/6/1000/real_time | 142.32 | ns | 4775396 |\n| BM_dispenso_auto_chunk/2/1000/real_time | 142.80 | ns | 4655604 |\n| BM_dispenso_static_chunk/4/1000/real_time | 143.00 | ns | 4820496 |\n| BM_dispenso_static_chunk/48/1000/real_time | 143.60 | ns | 4853788 |\n| BM_dispenso_static_chunk/3/1000/real_time | 143.72 | ns | 4827490 |\n| BM_dispenso_auto_chunk/16/1000/real_time | 143.88 | ns | 4638784 |\n| BM_dispenso_auto_chunk/24/1000/real_time | 143.88 | ns | 4645745 |\n| BM_dispenso/1/1000/real_time | 143.89 | ns | 4872629 |\n| BM_dispenso_auto_chunk/6/1000/real_time | 144.36 | ns | 4829474 |\n| BM_dispenso/2/1000/real_time | 144.50 | ns | 4899809 |\n| BM_dispenso_static_chunk/64/1000/real_time | 144.60 | ns | 4643943 |\n| BM_dispenso/8/1000/real_time | 144.95 | ns | 4617960 |\n| BM_dispenso_static_chunk/2/1000/real_time | 145.21 | ns | 4933091 |\n| BM_dispenso_auto_chunk/8/1000/real_time | 145.29 | ns | 4623094 |\n| BM_dispenso_static_chunk/24/1000/real_time | 145.34 | ns | 4687311 |\n| BM_dispenso_static_chunk/16/1000/real_time | 145.60 | ns | 4824891 |\n| BM_dispenso/6/1000/real_time | 145.71 | ns | 4548093 |\n| BM_dispenso/4/1000/real_time | 145.86 | ns | 4323846 |\n| BM_dispenso/24/1000/real_time | 146.00 | ns | 4705833 |\n| BM_dispenso_auto_chunk/1/1000/real_time | 146.07 | ns | 4848534 |\n| BM_dispenso/64/1000/real_time | 146.19 | ns | 4829106 |\n| BM_dispenso_auto_chunk/64/1000/real_time | 146.46 | ns | 4727871 |\n| BM_dispenso_static_chunk/96/1000/real_time | 146.70 | ns | 4626550 |\n| BM_dispenso_static_chunk/128/1000/real_time | 146.75 | ns | 4657266 |\n| BM_dispenso_auto_chunk/32/1000/real_time | 146.77 | ns | 4575927 |\n| BM_dispenso_auto_chunk/4/1000/real_time | 147.13 | ns | 4916734 |\n| BM_dispenso_auto_chunk/48/1000/real_time | 147.15 | ns | 4514336 |\n| BM_dispenso_auto_chunk/3/1000/real_time | 147.25 | ns | 4639890 |\n| BM_dispenso/16/1000/real_time | 147.55 | ns | 4708715 |\n| BM_dispenso_static_chunk/12/1000/real_time | 147.71 | ns | 4851106 |\n| BM_dispenso/3/1000/real_time | 148.10 | ns | 4837754 |\n| BM_dispenso_static_chunk/32/1000/real_time | 148.20 | ns | 4503125 |\n| BM_dispenso/12/1000/real_time | 148.41 | ns | 4801536 |\n| BM_dispenso/32/1000/real_time | 148.81 | ns | 4802635 |\n| BM_dispenso_auto_chunk/192/1000/real_time | 149.35 | ns | 4594436 |\n| BM_dispenso/48/1000/real_time | 150.04 | ns | 4543323 |\n| BM_dispenso/96/1000/real_time | 150.30 | ns | 4516922 |\n| BM_dispenso_static_chunk/192/1000/real_time | 150.42 | ns | 4619043 |\n| BM_dispenso/192/1000/real_time | 151.30 | ns | 4645230 |\n| BM_dispenso_auto_chunk/128/1000/real_time | 152.30 | ns | 4570080 |\n| BM_dispenso/128/1000/real_time | 152.83 | ns | 4656918 |\n| BM_dispenso_auto_chunk/96/1000/real_time | 153.25 | ns | 4631554 |\n| BM_omp/1/1000/real_time | 824.39 | ns | 876416 |\n| BM_omp/2/1000/real_time | 1485.19 | ns | 453712 |\n| BM_omp/3/1000/real_time | 1492.21 | ns | 464186 |\n| BM_omp/6/1000/real_time | 1579.97 | ns | 467615 |\n| BM_omp/4/1000/real_time | 1624.42 | ns | 473894 |\n| BM_omp/8/1000/real_time | 2135.85 | ns | 420350 |\n| BM_omp/12/1000/real_time | 3125.43 | ns | 229073 |\n| BM_omp/16/1000/real_time | 3535.99 | ns | 197394 |\n| BM_omp/24/1000/real_time | 5344.37 | ns | 126386 |\n| BM_omp/32/1000/real_time | 6769.37 | ns | 106128 |\n| BM_omp/48/1000/real_time | 9171.90 | ns | 75701 |\n| BM_omp/64/1000/real_time | 11898.31 | ns | 58889 |\n| BM_omp/32/1000000/real_time | 12512.92 | ns | 54617 |\n| BM_omp/24/1000000/real_time | 12954.34 | ns | 53572 |\n| BM_omp/48/1000000/real_time | 13276.90 | ns | 51749 |\n| BM_omp/64/1000000/real_time | 15448.39 | ns | 44999 |\n| BM_omp/16/1000000/real_time | 15669.81 | ns | 43324 |\n| BM_tbb/192/1000/real_time | 16496.57 | ns | 44009 |\n| BM_omp/96/1000/real_time | 16814.97 | ns | 41254 |\n| BM_tbb/96/1000/real_time | 17728.43 | ns | 39737 |\n| BM_omp/12/1000000/real_time | 17871.82 | ns | 37721 |\n| BM_tbb/32/1000/real_time | 17941.87 | ns | 38430 |\n| BM_tbb/128/1000/real_time | 19067.40 | ns | 36288 |\n| BM_tbb/64/1000/real_time | 19077.73 | ns | 35584 |\n| BM_tbb/24/1000/real_time | 19234.59 | ns | 36211 |\n| BM_tbb/48/1000/real_time | 19847.06 | ns | 35060 |\n| BM_tbb/3/1000/real_time | 20079.14 | ns | 35469 |\n| BM_tbb/16/1000/real_time | 20757.42 | ns | 33853 |\n| BM_omp/96/1000000/real_time | 20873.84 | ns | 33191 |\n| BM_tbb/8/1000/real_time | 21176.99 | ns | 32118 |\n| BM_tbb/12/1000/real_time | 21426.87 | ns | 32203 |\n| BM_tbb/6/1000/real_time | 21552.50 | ns | 33389 |\n| BM_tbb/4/1000/real_time | 21585.68 | ns | 36187 |\n| BM_tbb/2/1000/real_time | 22231.27 | ns | 30352 |\n| BM_omp/128/1000/real_time | 23381.80 | ns | 29497 |\n| BM_tbb/1/1000/real_time | 24774.84 | ns | 28307 |\n| BM_omp/8/1000000/real_time | 25386.69 | ns | 29310 |\n| BM_omp/128/1000000/real_time | 25990.22 | ns | 26547 |\n| BM_omp/6/1000000/real_time | 29647.25 | ns | 23418 |\n| BM_omp/4/1000000/real_time | 41452.53 | ns | 17089 |\n| BM_dispenso_static_chunk/64/1000000/real_time | 42483.29 | ns | 16006 |\n| BM_dispenso_static_chunk/48/1000000/real_time | 43534.16 | ns | 15999 |\n| BM_dispenso/64/1000000/real_time | 44074.44 | ns | 15816 |\n| BM_dispenso_auto_chunk/48/1000000/real_time | 44168.52 | ns | 15715 |\n| BM_dispenso_auto_chunk/64/1000000/real_time | 44650.27 | ns | 16033 |\n| BM_dispenso/48/1000000/real_time | 45129.76 | ns | 16331 |\n| BM_dispenso_static_chunk/24/1000000/real_time | 45622.64 | ns | 15256 |\n| BM_dispenso_auto_chunk/24/1000000/real_time | 46468.22 | ns | 15339 |\n| BM_dispenso_static_chunk/32/1000000/real_time | 46784.87 | ns | 14605 |\n| BM_dispenso/32/1000000/real_time | 46798.52 | ns | 15356 |\n| BM_dispenso_static_chunk/12/1000000/real_time | 47198.49 | ns | 13471 |\n| BM_dispenso_auto_chunk/32/1000000/real_time | 47425.30 | ns | 14760 |\n| BM_dispenso/24/1000000/real_time | 47515.48 | ns | 15223 |\n| BM_dispenso/16/1000000/real_time | 47543.43 | ns | 14098 |\n| BM_dispenso_auto_chunk/12/1000000/real_time | 47636.66 | ns | 15261 |\n| BM_dispenso_auto_chunk/16/1000000/real_time | 48238.79 | ns | 13659 |\n| BM_dispenso_static_chunk/16/1000000/real_time | 48902.05 | ns | 14448 |\n| BM_dispenso/12/1000000/real_time | 49467.11 | ns | 14992 |\n| BM_tbb/128/1000000/real_time | 50951.47 | ns | 12742 |\n| BM_dispenso/8/1000000/real_time | 52919.55 | ns | 12929 |\n| BM_dispenso_static_chunk/8/1000000/real_time | 52957.56 | ns | 13328 |\n| BM_dispenso_auto_chunk/8/1000000/real_time | 52986.65 | ns | 12834 |\n| BM_tbb/64/1000000/real_time | 53666.34 | ns | 12759 |\n| BM_tbb/96/1000000/real_time | 53669.19 | ns | 13123 |\n| BM_omp/3/1000000/real_time | 53903.25 | ns | 13113 |\n| BM_tbb/48/1000000/real_time | 55952.78 | ns | 12355 |\n| BM_dispenso_static_chunk/96/1000000/real_time | 56094.43 | ns | 11148 |\n| BM_dispenso_auto_chunk/96/1000000/real_time | 58046.06 | ns | 12962 |\n| BM_dispenso/96/1000000/real_time | 58499.99 | ns | 11822 |\n| BM_dispenso/6/1000000/real_time | 58817.88 | ns | 11329 |\n| BM_dispenso/128/1000000/real_time | 59352.12 | ns | 11991 |\n| BM_dispenso_auto_chunk/128/1000000/real_time | 60581.67 | ns | 11036 |\n| BM_dispenso_static_chunk/6/1000000/real_time | 61099.99 | ns | 11308 |\n| BM_dispenso_auto_chunk/6/1000000/real_time | 61320.21 | ns | 11474 |\n| BM_dispenso_static_chunk/128/1000000/real_time | 61801.82 | ns | 10994 |\n| BM_dispenso_auto_chunk/192/1000000/real_time | 62319.35 | ns | 11167 |\n| BM_dispenso/192/1000000/real_time | 63878.29 | ns | 11055 |\n| BM_dispenso_static_chunk/192/1000000/real_time | 63937.02 | ns | 10783 |\n| BM_tbb/32/1000000/real_time | 64336.80 | ns | 10749 |\n| BM_tbb/192/1000000/real_time | 68518.47 | ns | 9474 |\n| BM_tbb/24/1000000/real_time | 69249.19 | ns | 10049 |\n| BM_dispenso/4/1000000/real_time | 76785.94 | ns | 8983 |\n| BM_tbb/16/1000000/real_time | 76896.40 | ns | 8848 |\n| BM_omp/2/1000000/real_time | 78187.48 | ns | 9074 |\n| BM_dispenso_static_chunk/4/1000000/real_time | 78766.94 | ns | 8778 |\n| BM_dispenso_auto_chunk/4/1000000/real_time | 80370.59 | ns | 8725 |\n| BM_tbb/12/1000000/real_time | 81793.07 | ns | 8029 |\n| BM_tbb/8/1000000/real_time | 95906.80 | ns | 6798 |\n| BM_dispenso_auto_chunk/3/1000000/real_time | 99208.27 | ns | 6673 |\n| BM_dispenso_static_chunk/3/1000000/real_time | 99735.54 | ns | 6849 |\n| BM_dispenso/3/1000000/real_time | 100608.57 | ns | 6994 |\n| BM_tbb/6/1000000/real_time | 112290.76 | ns | 6342 |\n| BM_dispenso/2/1000000/real_time | 130656.08 | ns | 4831 |\n| BM_dispenso_static_chunk/2/1000000/real_time | 139543.52 | ns | 5065 |\n| BM_dispenso_auto_chunk/2/1000000/real_time | 139560.82 | ns | 5003 |\n| BM_tbb/4/1000000/real_time | 139698.55 | ns | 4860 |\n| BM_dispenso/1/1000000/real_time | 139867.37 | ns | 4932 |\n| BM_serial<kMediumSize> | 140220.02 | ns | 5058 |\n| BM_dispenso_auto_chunk/1/1000000/real_time | 140546.11 | ns | 4826 |\n| BM_dispenso_static_chunk/1/1000000/real_time | 141729.42 | ns | 5001 |\n| BM_omp/1/1000000/real_time | 142139.26 | ns | 4901 |\n| BM_tbb/3/1000000/real_time | 159286.10 | ns | 4372 |\n| BM_tbb/2/1000000/real_time | 197691.51 | ns | 3473 |\n| BM_tbb/1/1000000/real_time | 255397.88 | ns | 2790 |\n| BM_taskflow/1/1000/real_time | 546853.21 | ns | 5334 |\n| BM_omp/192/1000000/real_time | 547192.66 | ns | 1000 |\n| BM_taskflow/16/1000/real_time | 569910.03 | ns | 1000 |\n| BM_taskflow/4/1000/real_time | 591469.37 | ns | 4293 |\n| BM_taskflow/6/1000/real_time | 609230.57 | ns | 3491 |\n| BM_taskflow/3/1000/real_time | 622502.10 | ns | 5007 |\n| BM_taskflow/8/1000/real_time | 654998.49 | ns | 2465 |\n| BM_taskflow/2/1000/real_time | 674280.79 | ns | 5072 |\n| BM_taskflow/12/1000/real_time | 690982.66 | ns | 1457 |\n| BM_taskflow/24/1000/real_time | 712484.07 | ns | 1000 |\n| BM_taskflow/32/1000/real_time | 785106.94 | ns | 1000 |\n| BM_omp/192/1000/real_time | 806858.36 | ns | 1000 |\n| BM_taskflow/48/1000/real_time | 916306.38 | ns | 1000 |\n| BM_taskflow/64/1000/real_time | 1024707.12 | ns | 1000 |\n| BM_taskflow/96/1000/real_time | 1245541.96 | ns | 1000 |\n| BM_taskflow/128/1000/real_time | 1499205.95 | ns | 1000 |\n| BM_taskflow/192/1000/real_time | 1973161.65 | ns | 931 |\n| BM_omp/96/100000000/real_time | 3024072.90 | ns | 231 |\n| BM_omp/128/100000000/real_time | 3029329.27 | ns | 226 |\n| BM_omp/64/100000000/real_time | 3286724.07 | ns | 213 |\n| BM_omp/48/100000000/real_time | 3956450.14 | ns | 180 |\n| BM_taskflow/6/1000000/real_time | 4794919.01 | ns | 278 |\n| BM_dispenso/128/100000000/real_time | 4871390.20 | ns | 144 |\n| BM_dispenso_static_chunk/128/100000000/real_time | 4883607.76 | ns | 140 |\n| BM_dispenso_auto_chunk/128/100000000/real_time | 4902677.42 | ns | 143 |\n| BM_dispenso/96/100000000/real_time | 5012123.90 | ns | 100 |\n| BM_dispenso_auto_chunk/96/100000000/real_time | 5017875.45 | ns | 138 |\n| BM_dispenso_static_chunk/96/100000000/real_time | 5040013.72 | ns | 100 |\n| BM_dispenso_auto_chunk/192/100000000/real_time | 5047666.54 | ns | 100 |\n| BM_dispenso_static_chunk/192/100000000/real_time | 5061805.50 | ns | 141 |\n| BM_omp/32/100000000/real_time | 5229961.34 | ns | 116 |\n| BM_dispenso/192/100000000/real_time | 5276330.54 | ns | 100 |\n| BM_taskflow/96/1000000/real_time | 5429429.76 | ns | 353 |\n| BM_dispenso/64/100000000/real_time | 5482465.32 | ns | 128 |\n| BM_dispenso_static_chunk/64/100000000/real_time | 5543290.59 | ns | 130 |\n| BM_taskflow/192/1000000/real_time | 5592182.53 | ns | 327 |\n| BM_dispenso_auto_chunk/64/100000000/real_time | 5612907.01 | ns | 129 |\n| BM_taskflow/128/1000000/real_time | 5625497.53 | ns | 356 |\n| BM_taskflow/48/1000000/real_time | 5689053.22 | ns | 324 |\n| BM_dispenso/48/100000000/real_time | 5886660.78 | ns | 125 |\n| BM_dispenso_auto_chunk/48/100000000/real_time | 5920482.75 | ns | 118 |\n| BM_taskflow/64/1000000/real_time | 5948174.54 | ns | 364 |\n| BM_dispenso_static_chunk/48/100000000/real_time | 6010324.29 | ns | 128 |\n| BM_omp/192/100000000/real_time | 6108128.23 | ns | 104 |\n| BM_taskflow/32/1000000/real_time | 6171818.82 | ns | 315 |\n| BM_taskflow/3/1000000/real_time | 6219568.19 | ns | 193 |\n| BM_tbb/24/100000000/real_time | 6263228.29 | ns | 133 |\n| BM_taskflow/24/1000000/real_time | 6275633.12 | ns | 304 |\n| BM_taskflow/8/1000000/real_time | 6300312.71 | ns | 311 |\n| BM_dispenso_static_chunk/32/100000000/real_time | 6389218.51 | ns | 114 |\n| BM_dispenso_auto_chunk/32/100000000/real_time | 6546843.06 | ns | 108 |\n| BM_dispenso/32/100000000/real_time | 6593421.50 | ns | 116 |\n| BM_taskflow/2/1000000/real_time | 6604859.86 | ns | 153 |\n| BM_omp/24/100000000/real_time | 6626516.27 | ns | 107 |\n| BM_taskflow/16/1000000/real_time | 6650885.28 | ns | 302 |\n| BM_taskflow/12/1000000/real_time | 6813020.88 | ns | 279 |\n| BM_tbb/64/100000000/real_time | 6981095.82 | ns | 100 |\n| BM_tbb/32/100000000/real_time | 6986328.10 | ns | 100 |\n| BM_tbb/16/100000000/real_time | 7093342.71 | ns | 94 |\n| BM_taskflow/4/1000000/real_time | 7113504.38 | ns | 282 |\n| BM_tbb/48/100000000/real_time | 7114865.59 | ns | 100 |\n| BM_dispenso/24/100000000/real_time | 7250097.49 | ns | 122 |\n| BM_taskflow/1/1000000/real_time | 7279314.77 | ns | 100 |\n| BM_tbb/96/100000000/real_time | 7536042.17 | ns | 100 |\n| BM_dispenso_auto_chunk/24/100000000/real_time | 7583352.84 | ns | 106 |\n| BM_tbb/128/100000000/real_time | 7682778.87 | ns | 100 |\n| BM_dispenso_static_chunk/24/100000000/real_time | 7857890.08 | ns | 109 |\n| BM_tbb/12/100000000/real_time | 8902565.91 | ns | 112 |\n| BM_tbb/192/100000000/real_time | 9091760.25 | ns | 109 |\n| BM_dispenso_auto_chunk/16/100000000/real_time | 9122424.86 | ns | 81 |\n| BM_dispenso_static_chunk/16/100000000/real_time | 9306342.17 | ns | 78 |\n| BM_omp/16/100000000/real_time | 9350205.62 | ns | 72 |\n| BM_dispenso/16/100000000/real_time | 9860906.70 | ns | 71 |\n| BM_dispenso_static_chunk/12/100000000/real_time | 10026766.90 | ns | 86 |\n| BM_dispenso_auto_chunk/12/100000000/real_time | 10832385.27 | ns | 70 |\n| BM_tbb/8/100000000/real_time | 11004281.72 | ns | 89 |\n| BM_omp/12/100000000/real_time | 11133746.28 | ns | 56 |\n| BM_dispenso/12/100000000/real_time | 11271231.90 | ns | 78 |\n| BM_dispenso_static_chunk/8/100000000/real_time | 13059871.40 | ns | 59 |\n| BM_dispenso_auto_chunk/8/100000000/real_time | 13938469.56 | ns | 58 |\n| BM_dispenso/8/100000000/real_time | 14192208.92 | ns | 69 |\n| BM_tbb/6/100000000/real_time | 15095988.10 | ns | 49 |\n| BM_dispenso/6/100000000/real_time | 15647722.28 | ns | 58 |\n| BM_omp/8/100000000/real_time | 15955504.03 | ns | 55 |\n| BM_tbb/4/100000000/real_time | 16061379.37 | ns | 56 |\n| BM_tbb/3/100000000/real_time | 16766594.97 | ns | 37 |\n| BM_dispenso_static_chunk/6/100000000/real_time | 17353821.75 | ns | 45 |\n| BM_dispenso_auto_chunk/6/100000000/real_time | 17432353.05 | ns | 50 |\n| BM_tbb/2/100000000/real_time | 17741018.30 | ns | 37 |\n| BM_dispenso_static_chunk/4/100000000/real_time | 17982644.39 | ns | 39 |\n| BM_dispenso/4/100000000/real_time | 18014059.96 | ns | 40 |\n| BM_omp/6/100000000/real_time | 18132007.53 | ns | 38 |\n| BM_omp/3/100000000/real_time | 18203397.16 | ns | 37 |\n| BM_dispenso_auto_chunk/3/100000000/real_time | 18494825.00 | ns | 37 |\n| BM_dispenso/3/100000000/real_time | 18509418.05 | ns | 34 |\n| BM_dispenso_static_chunk/3/100000000/real_time | 18927706.66 | ns | 36 |\n| BM_dispenso_auto_chunk/4/100000000/real_time | 19038795.34 | ns | 36 |\n| BM_omp/4/100000000/real_time | 19171603.23 | ns | 37 |\n| BM_dispenso/2/100000000/real_time | 19473719.25 | ns | 34 |\n| BM_omp/2/100000000/real_time | 19527442.35 | ns | 42 |\n| BM_dispenso_auto_chunk/2/100000000/real_time | 19951961.30 | ns | 35 |\n| BM_dispenso_static_chunk/2/100000000/real_time | 20187116.00 | ns | 37 |\n| BM_omp/1/100000000/real_time | 20525771.74 | ns | 34 |\n| BM_dispenso_static_chunk/1/100000000/real_time | 20580910.42 | ns | 34 |\n| BM_dispenso_auto_chunk/1/100000000/real_time | 20762949.31 | ns | 34 |\n| BM_tbb/1/100000000/real_time | 20866145.35 | ns | 31 |\n| BM_dispenso/1/100000000/real_time | 21120260.68 | ns | 31 |\n| BM_serial<kLargeSize> | 26428675.59 | ns | 24 |\n| BM_taskflow/128/100000000/real_time | 59453268.75 | ns | 34 |\n| BM_taskflow/8/100000000/real_time | 62595140.93 | ns | 10 |\n| BM_taskflow/192/100000000/real_time | 64361602.42 | ns | 37 |\n| BM_taskflow/64/100000000/real_time | 66684033.89 | ns | 34 |\n| BM_taskflow/16/100000000/real_time | 66729991.00 | ns | 16 |\n| BM_taskflow/48/100000000/real_time | 67627636.19 | ns | 32 |\n| BM_taskflow/96/100000000/real_time | 68590896.81 | ns | 37 |\n| BM_taskflow/12/100000000/real_time | 68997006.20 | ns | 14 |\n| BM_taskflow/6/100000000/real_time | 72940928.30 | ns | 10 |\n| BM_taskflow/24/100000000/real_time | 73777416.03 | ns | 27 |\n| BM_taskflow/32/100000000/real_time | 74728069.76 | ns | 30 |\n| BM_taskflow/4/100000000/real_time | 86045934.82 | ns | 10 |\n| BM_taskflow/3/100000000/real_time | 89860309.85 | ns | 10 |\n| BM_taskflow/1/100000000/real_time | 114558587.60 | ns | 10 |\n| BM_taskflow/2/100000000/real_time | 119014025.11 | ns | 10 |\n"
  },
  {
    "path": "docs/benchmarks/simple_pool_details.md",
    "content": "# simple_pool - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso/1/1000/real_time | 10.54 | us | 64357 |\n| BM_tbb/1/1000/real_time | 23.99 | us | 29270 |\n| BM_tbb/3/1000/real_time | 25.46 | us | 26479 |\n| BM_tbb/2/1000/real_time | 26.13 | us | 26181 |\n| BM_tbb/4/1000/real_time | 27.32 | us | 26363 |\n| BM_tbb/8/1000/real_time | 29.91 | us | 23777 |\n| BM_tbb/6/1000/real_time | 30.28 | us | 24338 |\n| BM_tbb/12/1000/real_time | 41.60 | us | 16963 |\n| BM_tbb/16/1000/real_time | 68.23 | us | 9860 |\n| BM_tbb/24/1000/real_time | 97.13 | us | 6297 |\n| BM_dispenso/1/10000/real_time | 103.31 | us | 6741 |\n| BM_folly/1/1000/real_time | 189.08 | us | 3242 |\n| BM_dispenso/4/1000/real_time | 193.91 | us | 3451 |\n| BM_dispenso/6/1000/real_time | 197.88 | us | 3094 |\n| BM_dispenso/8/1000/real_time | 202.04 | us | 3371 |\n| BM_dispenso/12/1000/real_time | 209.83 | us | 3367 |\n| BM_dispenso/3/1000/real_time | 211.28 | us | 3041 |\n| BM_dispenso/16/1000/real_time | 224.00 | us | 2661 |\n| BM_dispenso/32/1000/real_time | 224.37 | us | 2571 |\n| BM_dispenso/24/1000/real_time | 224.76 | us | 2819 |\n| BM_dispenso/2/1000/real_time | 248.56 | us | 2574 |\n| BM_folly/2/1000/real_time | 252.88 | us | 2717 |\n| BM_tbb/1/10000/real_time | 256.21 | us | 2810 |\n| BM_tbb/2/10000/real_time | 263.70 | us | 2750 |\n| BM_tbb/32/1000/real_time | 268.08 | us | 2566 |\n| BM_tbb/3/10000/real_time | 273.28 | us | 2617 |\n| BM_folly/3/1000/real_time | 277.40 | us | 2274 |\n| BM_folly/4/1000/real_time | 279.80 | us | 2119 |\n| BM_folly/32/1000/real_time | 281.06 | us | 2307 |\n| BM_folly/12/1000/real_time | 281.56 | us | 2337 |\n| BM_tbb/4/10000/real_time | 282.90 | us | 2519 |\n| BM_folly/6/1000/real_time | 291.55 | us | 2422 |\n| BM_folly/24/1000/real_time | 294.30 | us | 2334 |\n| BM_folly/8/1000/real_time | 294.66 | us | 2194 |\n| BM_tbb/6/10000/real_time | 296.90 | us | 2353 |\n| BM_folly/96/1000/real_time | 311.25 | us | 1828 |\n| BM_folly/64/1000/real_time | 314.58 | us | 2212 |\n| BM_tbb/8/10000/real_time | 323.82 | us | 2055 |\n| BM_folly/48/1000/real_time | 330.89 | us | 2200 |\n| BM_dispenso/48/1000/real_time | 339.89 | us | 1689 |\n| BM_folly/192/1000/real_time | 340.91 | us | 1736 |\n| BM_tbb/48/1000/real_time | 348.14 | us | 1938 |\n| BM_folly/128/1000/real_time | 378.25 | us | 1850 |\n| BM_folly/16/1000/real_time | 382.47 | us | 2071 |\n| BM_dispenso/64/1000/real_time | 395.60 | us | 1788 |\n| BM_dispenso/192/1000/real_time | 430.14 | us | 1549 |\n| BM_dispenso/96/1000/real_time | 449.10 | us | 1427 |\n| BM_dispenso/128/1000/real_time | 469.87 | us | 1401 |\n| BM_tbb/12/10000/real_time | 473.20 | us | 1493 |\n| BM_tbb/64/1000/real_time | 601.56 | us | 1127 |\n| BM_tbb/16/10000/real_time | 642.88 | us | 1091 |\n| BM_tbb/192/1000/real_time | 1070.97 | us | 681 |\n| BM_tbb/96/1000/real_time | 1084.40 | us | 651 |\n| BM_tbb/128/1000/real_time | 1408.03 | us | 509 |\n| BM_tbb/24/10000/real_time | 1724.75 | us | 471 |\n| BM_folly/1/10000/real_time | 1892.82 | us | 365 |\n| BM_dispenso/2/10000/real_time | 1933.88 | us | 1000 |\n| BM_dispenso/16/10000/real_time | 1979.87 | us | 332 |\n| BM_dispenso/4/10000/real_time | 1997.91 | us | 338 |\n| BM_dispenso/3/10000/real_time | 2027.29 | us | 328 |\n| BM_dispenso/32/10000/real_time | 2326.35 | us | 295 |\n| BM_dispenso/8/10000/real_time | 2523.80 | us | 274 |\n| BM_dispenso/24/10000/real_time | 2537.17 | us | 305 |\n| BM_folly/2/10000/real_time | 2542.00 | us | 254 |\n| BM_dispenso/6/10000/real_time | 2569.74 | us | 343 |\n| BM_dispenso/12/10000/real_time | 2677.61 | us | 330 |\n| BM_folly/4/10000/real_time | 2680.21 | us | 217 |\n| BM_folly/8/10000/real_time | 2755.67 | us | 232 |\n| BM_tbb/32/10000/real_time | 2807.62 | us | 237 |\n| BM_folly/6/10000/real_time | 2814.11 | us | 252 |\n| BM_folly/48/10000/real_time | 2826.28 | us | 215 |\n| BM_folly/12/10000/real_time | 2844.92 | us | 223 |\n| BM_folly/3/10000/real_time | 2852.37 | us | 244 |\n| BM_folly/64/10000/real_time | 2870.29 | us | 191 |\n| BM_folly/16/10000/real_time | 2914.58 | us | 240 |\n| BM_folly/24/10000/real_time | 3109.16 | us | 250 |\n| BM_folly/32/10000/real_time | 3169.13 | us | 197 |\n| BM_folly/96/10000/real_time | 3194.18 | us | 185 |\n| BM_dispenso/48/10000/real_time | 3601.29 | us | 207 |\n| BM_folly/128/10000/real_time | 3649.48 | us | 186 |\n| BM_folly/192/10000/real_time | 3743.20 | us | 178 |\n| BM_tbb/48/10000/real_time | 3929.30 | us | 179 |\n| BM_dispenso/64/10000/real_time | 3938.29 | us | 187 |\n| BM_dispenso/96/10000/real_time | 4372.46 | us | 168 |\n| BM_tbb/64/10000/real_time | 5224.33 | us | 100 |\n| BM_dispenso/128/10000/real_time | 6107.40 | us | 112 |\n| BM_dispenso/192/10000/real_time | 6420.05 | us | 117 |\n| BM_tbb/96/10000/real_time | 7034.69 | us | 105 |\n| BM_tbb/128/10000/real_time | 9558.52 | us | 91 |\n| BM_dispenso/1/1000000/real_time | 10366.97 | us | 69 |\n| BM_tbb/192/10000/real_time | 10396.79 | us | 68 |\n| BM_tbb/2/1000000/real_time | 35423.01 | us | 19 |\n| BM_tbb/1/1000000/real_time | 35423.55 | us | 21 |\n| BM_tbb/3/1000000/real_time | 36120.21 | us | 19 |\n| BM_tbb/4/1000000/real_time | 39177.53 | us | 19 |\n| BM_tbb/6/1000000/real_time | 39235.43 | us | 18 |\n| BM_tbb/8/1000000/real_time | 41579.33 | us | 17 |\n| BM_tbb/12/1000000/real_time | 58430.34 | us | 9 |\n| BM_tbb/16/1000000/real_time | 73021.82 | us | 9 |\n| BM_dispenso/2/1000000/real_time | 89328.89 | us | 10 |\n| BM_tbb/24/1000000/real_time | 157457.61 | us | 4 |\n| BM_dispenso/4/1000000/real_time | 189653.57 | us | 3 |\n| BM_dispenso/6/1000000/real_time | 198791.41 | us | 4 |\n| BM_dispenso/12/1000000/real_time | 206894.35 | us | 3 |\n| BM_dispenso/16/1000000/real_time | 213521.52 | us | 3 |\n| BM_dispenso/3/1000000/real_time | 218034.68 | us | 3 |\n| BM_folly/1/1000000/real_time | 222907.47 | us | 3 |\n| BM_dispenso/24/1000000/real_time | 233469.20 | us | 3 |\n| BM_dispenso/32/1000000/real_time | 240675.30 | us | 3 |\n| BM_dispenso/8/1000000/real_time | 245718.29 | us | 3 |\n| BM_folly/2/1000000/real_time | 246138.29 | us | 3 |\n| BM_folly/24/1000000/real_time | 267477.37 | us | 3 |\n| BM_folly/8/1000000/real_time | 273314.47 | us | 2 |\n| BM_tbb/32/1000000/real_time | 274023.20 | us | 3 |\n| BM_folly/3/1000000/real_time | 275581.05 | us | 2 |\n| BM_folly/4/1000000/real_time | 280519.61 | us | 3 |\n| BM_folly/16/1000000/real_time | 281471.96 | us | 2 |\n| BM_folly/64/1000000/real_time | 287401.70 | us | 2 |\n| BM_folly/32/1000000/real_time | 289419.48 | us | 2 |\n| BM_folly/12/1000000/real_time | 293979.88 | us | 3 |\n| BM_folly/48/1000000/real_time | 298945.00 | us | 2 |\n| BM_folly/6/1000000/real_time | 299810.47 | us | 2 |\n| BM_dispenso/48/1000000/real_time | 326641.45 | us | 2 |\n| BM_folly/96/1000000/real_time | 342863.21 | us | 2 |\n| BM_folly/128/1000000/real_time | 356469.77 | us | 2 |\n| BM_folly/192/1000000/real_time | 364121.04 | us | 2 |\n| BM_tbb/48/1000000/real_time | 455300.03 | us | 2 |\n| BM_tbb/64/1000000/real_time | 509988.19 | us | 1 |\n| BM_dispenso/64/1000000/real_time | 516101.40 | us | 1 |\n| BM_dispenso/96/1000000/real_time | 579200.28 | us | 1 |\n| BM_dispenso/128/1000000/real_time | 605308.39 | us | 1 |\n| BM_dispenso/192/1000000/real_time | 622963.62 | us | 1 |\n| BM_tbb/96/1000000/real_time | 724067.15 | us | 1 |\n| BM_tbb/128/1000000/real_time | 832571.89 | us | 1 |\n| BM_tbb/192/1000000/real_time | 1018550.28 | us | 1 |\n"
  },
  {
    "path": "docs/benchmarks/small_buffer_details.md",
    "content": "# small_buffer - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_newdelete<kSmallSize>/8192 | 79599.70 | ns | 8652 |\n| BM_newdelete<kSmallSize>/8192/threads:16 | 100415.84 | ns | 6768 |\n| BM_small_buffer_allocator<kLargeSize>/8192 | 112097.97 | ns | 6276 |\n| BM_small_buffer_allocator<kMediumSize>/8192 | 113413.43 | ns | 6119 |\n| BM_small_buffer_allocator<kSmallSize>/8192 | 151423.03 | ns | 4595 |\n| BM_small_buffer_allocator<kSmallSize>/8192/threads:16 | 196510.87 | ns | 3648 |\n| BM_small_buffer_allocator<kMediumSize>/8192/threads:16 | 215262.76 | ns | 3040 |\n| BM_small_buffer_allocator<kLargeSize>/8192/threads:16 | 237795.91 | ns | 2896 |\n| BM_newdelete<kSmallSize>/32768 | 333435.65 | ns | 2125 |\n| BM_newdelete<kSmallSize>/32768/threads:16 | 422098.80 | ns | 1632 |\n| BM_newdelete<kMediumSize>/8192 | 437184.17 | ns | 1565 |\n| BM_small_buffer_allocator<kMediumSize>/32768 | 449722.73 | ns | 1567 |\n| BM_small_buffer_allocator<kLargeSize>/32768 | 462629.58 | ns | 1577 |\n| BM_small_buffer_allocator<kSmallSize>/32768 | 589785.80 | ns | 1194 |\n| BM_newdelete<kMediumSize>/8192/threads:16 | 608506.93 | ns | 1104 |\n| BM_small_buffer_allocator<kSmallSize>/32768/threads:16 | 732593.81 | ns | 880 |\n| BM_newdelete<kLargeSize>/8192 | 778251.18 | ns | 908 |\n| BM_small_buffer_allocator<kMediumSize>/32768/threads:16 | 866150.93 | ns | 768 |\n| BM_small_buffer_allocator<kLargeSize>/32768/threads:16 | 951621.02 | ns | 704 |\n| BM_newdelete<kLargeSize>/8192/threads:16 | 1198657.34 | ns | 560 |\n| BM_newdelete<kMediumSize>/32768 | 2107102.61 | ns | 353 |\n| BM_newdelete<kMediumSize>/32768/threads:16 | 2983152.38 | ns | 224 |\n| BM_newdelete<kLargeSize>/32768 | 3427922.12 | ns | 208 |\n| BM_newdelete<kLargeSize>/32768/threads:16 | 57061692.12 | ns | 16 |\n"
  },
  {
    "path": "docs/benchmarks/summing_for_details.md",
    "content": "# summing_for - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_serial<kSmallSize> | 293.83 | ns | 2421485 |\n| BM_dispenso/32/1000/real_time | 303.68 | ns | 2163673 |\n| BM_dispenso/24/1000/real_time | 304.40 | ns | 2275773 |\n| BM_dispenso/3/1000/real_time | 305.75 | ns | 2161715 |\n| BM_dispenso/64/1000/real_time | 306.46 | ns | 2301338 |\n| BM_dispenso/12/1000/real_time | 307.29 | ns | 2281172 |\n| BM_dispenso/4/1000/real_time | 307.36 | ns | 2336169 |\n| BM_dispenso/128/1000/real_time | 307.60 | ns | 2282574 |\n| BM_dispenso/48/1000/real_time | 310.42 | ns | 2246353 |\n| BM_dispenso/96/1000/real_time | 312.39 | ns | 2235407 |\n| BM_dispenso/8/1000/real_time | 312.51 | ns | 2296342 |\n| BM_dispenso/16/1000/real_time | 312.57 | ns | 2232372 |\n| BM_dispenso/2/1000/real_time | 312.65 | ns | 2277051 |\n| BM_dispenso/6/1000/real_time | 315.57 | ns | 2279751 |\n| BM_dispenso/1/1000/real_time | 328.90 | ns | 2270562 |\n| BM_dispenso/192/1000/real_time | 333.18 | ns | 2070643 |\n| BM_omp/1/1000/real_time | 979.75 | ns | 695515 |\n| BM_omp/3/1000/real_time | 1582.02 | ns | 419117 |\n| BM_omp/4/1000/real_time | 1594.61 | ns | 433390 |\n| BM_omp/2/1000/real_time | 1629.78 | ns | 444018 |\n| BM_omp/6/1000/real_time | 1712.38 | ns | 445655 |\n| BM_omp/8/1000/real_time | 1937.83 | ns | 324890 |\n| BM_omp/12/1000/real_time | 2986.33 | ns | 233931 |\n| BM_omp/16/1000/real_time | 3931.25 | ns | 193648 |\n| BM_omp/24/1000/real_time | 5685.50 | ns | 115632 |\n| BM_omp/32/1000/real_time | 7349.03 | ns | 94335 |\n| BM_omp/48/1000/real_time | 10582.43 | ns | 65859 |\n| BM_omp/64/1000/real_time | 13590.13 | ns | 51023 |\n| BM_tbb/192/1000/real_time | 15801.22 | ns | 40844 |\n| BM_omp/48/1000000/real_time | 16360.23 | ns | 42532 |\n| BM_omp/64/1000000/real_time | 17751.29 | ns | 39388 |\n| BM_omp/32/1000000/real_time | 17793.64 | ns | 41819 |\n| BM_tbb/128/1000/real_time | 17815.97 | ns | 39000 |\n| BM_tbb/96/1000/real_time | 18143.36 | ns | 37680 |\n| BM_tbb/64/1000/real_time | 18989.70 | ns | 37047 |\n| BM_omp/24/1000000/real_time | 19174.97 | ns | 37530 |\n| BM_omp/96/1000/real_time | 19288.31 | ns | 36234 |\n| BM_tbb/48/1000/real_time | 19810.22 | ns | 34805 |\n| BM_tbb/32/1000/real_time | 21870.54 | ns | 31543 |\n| BM_tbb/6/1000/real_time | 21896.28 | ns | 32629 |\n| BM_tbb/4/1000/real_time | 23486.34 | ns | 29726 |\n| BM_omp/96/1000000/real_time | 23528.64 | ns | 29546 |\n| BM_tbb/24/1000/real_time | 23884.88 | ns | 29435 |\n| BM_omp/16/1000000/real_time | 24727.52 | ns | 26385 |\n| BM_tbb/3/1000/real_time | 24750.63 | ns | 28189 |\n| BM_omp/128/1000/real_time | 25315.97 | ns | 27365 |\n| BM_tbb/16/1000/real_time | 26132.28 | ns | 26927 |\n| BM_tbb/2/1000/real_time | 26446.82 | ns | 25938 |\n| BM_tbb/8/1000/real_time | 26907.31 | ns | 29378 |\n| BM_tbb/12/1000/real_time | 27032.30 | ns | 25780 |\n| BM_tbb/1/1000/real_time | 28581.78 | ns | 24336 |\n| BM_dispenso/192/1000000/real_time | 29364.74 | ns | 21793 |\n| BM_omp/128/1000000/real_time | 29553.21 | ns | 23635 |\n| BM_omp/12/1000000/real_time | 30252.13 | ns | 22745 |\n| BM_dispenso/128/1000000/real_time | 30388.01 | ns | 23673 |\n| BM_dispenso/96/1000000/real_time | 31328.91 | ns | 23100 |\n| BM_tbb/192/1000000/real_time | 31411.03 | ns | 19743 |\n| BM_tbb/96/1000000/real_time | 36236.11 | ns | 18951 |\n| BM_tbb/128/1000000/real_time | 36968.26 | ns | 19132 |\n| BM_dispenso/64/1000000/real_time | 39064.25 | ns | 14773 |\n| BM_tbb/64/1000000/real_time | 40380.77 | ns | 17400 |\n| BM_omp/8/1000000/real_time | 42368.29 | ns | 16308 |\n| BM_tbb/48/1000000/real_time | 45433.36 | ns | 14911 |\n| BM_dispenso/48/1000000/real_time | 48646.49 | ns | 14360 |\n| BM_async/1/1000/real_time | 50876.75 | ns | 14112 |\n| BM_omp/6/1000000/real_time | 54949.86 | ns | 12157 |\n| BM_tbb/32/1000000/real_time | 54999.01 | ns | 11512 |\n| BM_dispenso/32/1000000/real_time | 56922.79 | ns | 12645 |\n| BM_dispenso/24/1000000/real_time | 61652.17 | ns | 13052 |\n| BM_tbb/24/1000000/real_time | 65647.93 | ns | 10636 |\n| BM_dispenso/16/1000000/real_time | 67001.75 | ns | 10080 |\n| BM_async/2/1000/real_time | 71990.09 | ns | 9658 |\n| BM_omp/4/1000000/real_time | 79126.38 | ns | 8771 |\n| BM_tbb/16/1000000/real_time | 80930.47 | ns | 8598 |\n| BM_dispenso/12/1000000/real_time | 81950.99 | ns | 8648 |\n| BM_async/3/1000/real_time | 93541.61 | ns | 7173 |\n| BM_tbb/12/1000000/real_time | 96547.34 | ns | 6977 |\n| BM_dispenso/8/1000000/real_time | 102814.55 | ns | 6863 |\n| BM_omp/3/1000000/real_time | 103848.32 | ns | 6900 |\n| BM_dispenso/6/1000000/real_time | 117963.27 | ns | 5713 |\n| BM_async/4/1000/real_time | 118024.91 | ns | 6153 |\n| BM_tbb/8/1000000/real_time | 121520.50 | ns | 5534 |\n| BM_tbb/6/1000000/real_time | 146487.97 | ns | 4621 |\n| BM_omp/2/1000000/real_time | 151358.08 | ns | 4596 |\n| BM_dispenso/4/1000000/real_time | 156793.06 | ns | 4475 |\n| BM_tbb/4/1000000/real_time | 192405.42 | ns | 3701 |\n| BM_dispenso/3/1000000/real_time | 198000.52 | ns | 3439 |\n| BM_tbb/3/1000000/real_time | 226115.43 | ns | 3082 |\n| BM_dispenso/2/1000000/real_time | 276074.72 | ns | 2366 |\n| BM_tbb/2/1000000/real_time | 283698.92 | ns | 2479 |\n| BM_serial<kMediumSize> | 288332.83 | ns | 2489 |\n| BM_dispenso/1/1000000/real_time | 289774.28 | ns | 2379 |\n| BM_omp/192/1000000/real_time | 295096.92 | ns | 12974 |\n| BM_omp/1/1000000/real_time | 296049.68 | ns | 2380 |\n| BM_async/4/1000000/real_time | 345505.83 | ns | 2063 |\n| BM_tbb/1/1000000/real_time | 389299.33 | ns | 1764 |\n| BM_async/3/1000000/real_time | 412842.51 | ns | 1769 |\n| BM_async/2/1000000/real_time | 597696.43 | ns | 1128 |\n| BM_omp/128/100000000/real_time | 796364.32 | ns | 824 |\n| BM_async/6/1000/real_time | 867389.99 | ns | 1749 |\n| BM_omp/192/1000/real_time | 895369.70 | ns | 10000 |\n| BM_async/1/1000000/real_time | 972322.79 | ns | 750 |\n| BM_omp/96/100000000/real_time | 981239.60 | ns | 716 |\n| BM_omp/64/100000000/real_time | 1009220.71 | ns | 724 |\n| BM_async/6/1000000/real_time | 1115505.46 | ns | 1000 |\n| BM_omp/48/100000000/real_time | 1137284.57 | ns | 574 |\n| BM_tbb/128/100000000/real_time | 1442124.58 | ns | 481 |\n| BM_tbb/96/100000000/real_time | 1454035.12 | ns | 465 |\n| BM_tbb/64/100000000/real_time | 1483187.66 | ns | 451 |\n| BM_tbb/48/100000000/real_time | 1515557.06 | ns | 457 |\n| BM_dispenso/192/100000000/real_time | 1737799.13 | ns | 397 |\n| BM_tbb/192/100000000/real_time | 1743130.58 | ns | 403 |\n| BM_dispenso/128/100000000/real_time | 1846680.61 | ns | 374 |\n| BM_tbb/32/100000000/real_time | 1961485.35 | ns | 332 |\n| BM_dispenso/96/100000000/real_time | 1984191.91 | ns | 367 |\n| BM_omp/32/100000000/real_time | 2064963.75 | ns | 347 |\n| BM_async/8/1000000/real_time | 2216675.86 | ns | 1000 |\n| BM_dispenso/64/100000000/real_time | 2334231.17 | ns | 306 |\n| BM_tbb/24/100000000/real_time | 2610180.18 | ns | 286 |\n| BM_dispenso/48/100000000/real_time | 2881569.87 | ns | 229 |\n| BM_omp/24/100000000/real_time | 3012322.41 | ns | 232 |\n| BM_dispenso/32/100000000/real_time | 3572259.89 | ns | 206 |\n| BM_async/8/1000/real_time | 4023138.00 | ns | 1000 |\n| BM_tbb/16/100000000/real_time | 4291873.83 | ns | 156 |\n| BM_dispenso/24/100000000/real_time | 4319180.90 | ns | 146 |\n| BM_omp/192/100000000/real_time | 4500926.72 | ns | 402 |\n| BM_omp/16/100000000/real_time | 4739963.64 | ns | 139 |\n| BM_tbb/12/100000000/real_time | 5022023.12 | ns | 100 |\n| BM_dispenso/16/100000000/real_time | 5971055.52 | ns | 100 |\n| BM_async/12/1000/real_time | 6033315.88 | ns | 1000 |\n| BM_async/12/1000000/real_time | 6247626.60 | ns | 100 |\n| BM_omp/12/100000000/real_time | 6489813.38 | ns | 101 |\n| BM_dispenso/12/100000000/real_time | 6893668.01 | ns | 126 |\n| BM_async/16/100000000/real_time | 7895807.43 | ns | 114 |\n| BM_tbb/8/100000000/real_time | 8118946.85 | ns | 127 |\n| BM_async/32/100000000/real_time | 8126280.75 | ns | 100 |\n| BM_async/24/100000000/real_time | 8579654.10 | ns | 100 |\n| BM_async/16/1000/real_time | 8856314.27 | ns | 1040 |\n| BM_omp/8/100000000/real_time | 9097573.55 | ns | 74 |\n| BM_async/12/100000000/real_time | 9529437.79 | ns | 95 |\n| BM_omp/6/100000000/real_time | 10114969.43 | ns | 66 |\n| BM_tbb/6/100000000/real_time | 10222572.02 | ns | 106 |\n| BM_async/8/100000000/real_time | 10432677.03 | ns | 66 |\n| BM_dispenso/8/100000000/real_time | 10448925.46 | ns | 79 |\n| BM_tbb/4/100000000/real_time | 10877465.47 | ns | 73 |\n| BM_omp/3/100000000/real_time | 11031112.15 | ns | 66 |\n| BM_omp/4/100000000/real_time | 11287493.34 | ns | 65 |\n| BM_tbb/3/100000000/real_time | 11293117.38 | ns | 61 |\n| BM_dispenso/6/100000000/real_time | 12560459.91 | ns | 58 |\n| BM_async/16/1000000/real_time | 14340933.37 | ns | 49 |\n| BM_omp/2/100000000/real_time | 14814295.83 | ns | 43 |\n| BM_tbb/2/100000000/real_time | 15326512.56 | ns | 45 |\n| BM_dispenso/4/100000000/real_time | 15513337.49 | ns | 51 |\n| BM_async/6/100000000/real_time | 17430620.52 | ns | 51 |\n| BM_dispenso/3/100000000/real_time | 18112291.99 | ns | 39 |\n| BM_dispenso/2/100000000/real_time | 19437694.18 | ns | 35 |\n| BM_async/4/100000000/real_time | 20126708.22 | ns | 35 |\n| BM_async/48/100000000/real_time | 22682058.50 | ns | 51 |\n| BM_async/24/1000000/real_time | 25457791.87 | ns | 47 |\n| BM_async/24/1000/real_time | 25487308.85 | ns | 47 |\n| BM_async/3/100000000/real_time | 26176047.08 | ns | 26 |\n| BM_omp/1/100000000/real_time | 28418058.38 | ns | 25 |\n| BM_dispenso/1/100000000/real_time | 28433731.83 | ns | 24 |\n| BM_serial<kLargeSize> | 29512667.33 | ns | 24 |\n| BM_tbb/1/100000000/real_time | 29538649.37 | ns | 24 |\n| BM_async/32/1000000/real_time | 33337548.69 | ns | 18 |\n| BM_async/32/1000/real_time | 34689523.04 | ns | 23 |\n| BM_async/2/100000000/real_time | 38728812.71 | ns | 18 |\n| BM_async/64/100000000/real_time | 39941762.63 | ns | 162 |\n| BM_async/64/1000/real_time | 41071485.19 | ns | 229 |\n| BM_async/96/100000000/real_time | 43392837.95 | ns | 70 |\n| BM_async/48/1000/real_time | 50104875.49 | ns | 10 |\n| BM_async/48/1000000/real_time | 59674201.35 | ns | 10 |\n| BM_async/64/1000000/real_time | 71744002.93 | ns | 7 |\n| BM_async/1/100000000/real_time | 73254492.55 | ns | 9 |\n| BM_async/128/100000000/real_time | 88639985.03 | ns | 106 |\n| BM_async/96/1000/real_time | 100230913.34 | ns | 7 |\n| BM_async/96/1000000/real_time | 113880544.90 | ns | 7 |\n| BM_async/128/1000000/real_time | 126038840.51 | ns | 4 |\n| BM_async/192/1000000/real_time | 140036053.79 | ns | 69 |\n| BM_async/128/1000/real_time | 149855462.83 | ns | 4 |\n| BM_async/192/100000000/real_time | 162569639.27 | ns | 10 |\n| BM_async/192/1000/real_time | 175513107.80 | ns | 4 |\n"
  },
  {
    "path": "docs/benchmarks/timed_task_details.md",
    "content": "# timed_task - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso<2,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso<4,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso<6,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso<2,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso<4,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso<6,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso_mixed<false>/manual_time | 100000000.00 | ns | 7 |\n| BM_dispenso_mixed<true>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<2,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<4,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<6,false>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<2,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<4,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly<6,true>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly_mixed<false>/manual_time | 100000000.00 | ns | 7 |\n| BM_folly_mixed<true>/manual_time | 100000000.00 | ns | 7 |\n"
  },
  {
    "path": "docs/benchmarks/trivial_compute_details.md",
    "content": "# trivial_compute - Detailed Results\n\n| Benchmark | Time | Unit | Iterations |\n|-----------|------|------|------------|\n| BM_dispenso/1/100/real_time | 1344.44 | ns | 506336 |\n| BM_dispenso/12/100/real_time | 1349.15 | ns | 507858 |\n| BM_dispenso/3/100/real_time | 1355.13 | ns | 471753 |\n| BM_dispenso/2/100/real_time | 1356.45 | ns | 512761 |\n| BM_dispenso/8/100/real_time | 1357.06 | ns | 519270 |\n| BM_dispenso/16/100/real_time | 1357.71 | ns | 490978 |\n| BM_dispenso/4/100/real_time | 1360.64 | ns | 514788 |\n| BM_dispenso/6/100/real_time | 1367.74 | ns | 501954 |\n| BM_dispenso/32/100/real_time | 1384.59 | ns | 497716 |\n| BM_serial<kSmallSize> | 1388.89 | ns | 535052 |\n| BM_dispenso/24/100/real_time | 1392.34 | ns | 500937 |\n| BM_dispenso/96/100/real_time | 1394.35 | ns | 487503 |\n| BM_dispenso/64/100/real_time | 1406.22 | ns | 503927 |\n| BM_dispenso/192/100/real_time | 1417.08 | ns | 477554 |\n| BM_dispenso/48/100/real_time | 1417.29 | ns | 487917 |\n| BM_dispenso/128/100/real_time | 1419.52 | ns | 487375 |\n| BM_omp/6/100/real_time | 1852.75 | ns | 372940 |\n| BM_omp/4/100/real_time | 1868.87 | ns | 366585 |\n| BM_omp/3/100/real_time | 1947.41 | ns | 361051 |\n| BM_omp/1/100/real_time | 2053.59 | ns | 341674 |\n| BM_omp/2/100/real_time | 2136.41 | ns | 334157 |\n| BM_omp/8/100/real_time | 2419.16 | ns | 306408 |\n| BM_omp/12/100/real_time | 3239.69 | ns | 223733 |\n| BM_omp/16/100/real_time | 3866.78 | ns | 173413 |\n| BM_omp/24/100/real_time | 6048.61 | ns | 107980 |\n| BM_omp/32/100/real_time | 7208.93 | ns | 91980 |\n| BM_tbb/1/100/real_time | 9956.27 | ns | 69526 |\n| BM_tbb/4/100/real_time | 10338.85 | ns | 62419 |\n| BM_omp/48/100/real_time | 10423.84 | ns | 65911 |\n| BM_tbb/2/100/real_time | 10580.14 | ns | 66164 |\n| BM_tbb/3/100/real_time | 10678.41 | ns | 65625 |\n| BM_tbb/6/100/real_time | 11047.83 | ns | 58719 |\n| BM_tbb/8/100/real_time | 11170.38 | ns | 58036 |\n| BM_tbb/12/100/real_time | 13128.97 | ns | 55863 |\n| BM_tbb/16/100/real_time | 13338.70 | ns | 52360 |\n| BM_omp/64/100/real_time | 13925.51 | ns | 52097 |\n| BM_tbb/192/100/real_time | 15354.70 | ns | 46192 |\n| BM_tbb/24/100/real_time | 15732.87 | ns | 43677 |\n| BM_tbb/32/100/real_time | 16213.78 | ns | 41827 |\n| BM_tbb/48/100/real_time | 16805.92 | ns | 42221 |\n| BM_tbb/64/100/real_time | 17084.22 | ns | 40515 |\n| BM_tbb/96/100/real_time | 18076.52 | ns | 38187 |\n| BM_tbb/128/100/real_time | 19383.07 | ns | 37343 |\n| BM_omp/96/100/real_time | 19984.33 | ns | 35070 |\n| BM_omp/128/100/real_time | 26077.38 | ns | 26849 |\n| BM_async/1/100/real_time | 52053.03 | ns | 13750 |\n| BM_async/2/100/real_time | 73590.79 | ns | 9433 |\n| BM_async/3/100/real_time | 94926.26 | ns | 7218 |\n| BM_async/4/100/real_time | 118803.99 | ns | 5783 |\n| BM_async/6/100/real_time | 632490.27 | ns | 3202 |\n| BM_tbb/128/1000000/real_time | 684519.56 | ns | 999 |\n| BM_tbb/192/1000000/real_time | 745564.94 | ns | 853 |\n| BM_tbb/96/1000000/real_time | 796475.15 | ns | 834 |\n| BM_omp/192/100/real_time | 842929.03 | ns | 1000 |\n| BM_omp/128/1000000/real_time | 1003604.88 | ns | 691 |\n| BM_tbb/64/1000000/real_time | 1024205.89 | ns | 655 |\n| BM_omp/96/1000000/real_time | 1177636.85 | ns | 579 |\n| BM_dispenso/192/1000000/real_time | 1257235.68 | ns | 612 |\n| BM_tbb/48/1000000/real_time | 1273336.71 | ns | 540 |\n| BM_dispenso/128/1000000/real_time | 1416916.31 | ns | 515 |\n| BM_dispenso/96/1000000/real_time | 1592645.49 | ns | 433 |\n| BM_omp/64/1000000/real_time | 1606785.48 | ns | 429 |\n| BM_tbb/32/1000000/real_time | 1838295.49 | ns | 392 |\n| BM_omp/48/1000000/real_time | 2020463.78 | ns | 341 |\n| BM_dispenso/64/1000000/real_time | 2160320.23 | ns | 338 |\n| BM_tbb/24/1000000/real_time | 2314908.94 | ns | 301 |\n| BM_dispenso/48/1000000/real_time | 2521290.78 | ns | 280 |\n| BM_omp/32/1000000/real_time | 2988591.88 | ns | 236 |\n| BM_dispenso/32/1000000/real_time | 3390598.72 | ns | 209 |\n| BM_tbb/16/1000000/real_time | 3442439.87 | ns | 201 |\n| BM_omp/24/1000000/real_time | 3776613.01 | ns | 184 |\n| BM_dispenso/24/1000000/real_time | 4273963.58 | ns | 166 |\n| BM_tbb/12/1000000/real_time | 4559491.65 | ns | 154 |\n| BM_async/8/100/real_time | 4698381.14 | ns | 1000 |\n| BM_omp/16/1000000/real_time | 5691946.09 | ns | 121 |\n| BM_dispenso/16/1000000/real_time | 6113660.04 | ns | 115 |\n| BM_omp/192/1000000/real_time | 6264927.94 | ns | 147 |\n| BM_tbb/8/1000000/real_time | 6942634.91 | ns | 102 |\n| BM_async/24/1000000/real_time | 7459626.13 | ns | 147 |\n| BM_omp/12/1000000/real_time | 7639101.94 | ns | 91 |\n| BM_dispenso/12/1000000/real_time | 8031436.69 | ns | 88 |\n| BM_async/12/1000000/real_time | 8385342.45 | ns | 85 |\n| BM_async/12/100/real_time | 8705155.72 | ns | 1000 |\n| BM_tbb/6/1000000/real_time | 8987983.20 | ns | 76 |\n| BM_async/16/1000000/real_time | 9150412.81 | ns | 108 |\n| BM_async/16/100/real_time | 9518732.86 | ns | 1097 |\n| BM_async/24/100/real_time | 9596137.81 | ns | 186 |\n| BM_omp/8/1000000/real_time | 11331613.07 | ns | 61 |\n| BM_dispenso/8/1000000/real_time | 11486515.08 | ns | 58 |\n| BM_tbb/4/1000000/real_time | 13230409.99 | ns | 54 |\n| BM_async/8/1000000/real_time | 13687067.44 | ns | 58 |\n| BM_async/32/100/real_time | 14020894.71 | ns | 230 |\n| BM_omp/6/1000000/real_time | 14770355.36 | ns | 46 |\n| BM_dispenso/6/1000000/real_time | 15103521.42 | ns | 47 |\n| BM_tbb/3/1000000/real_time | 17667740.63 | ns | 39 |\n| BM_async/6/1000000/real_time | 17886491.66 | ns | 44 |\n| BM_tbb/192/100000000/real_time | 18798915.17 | ns | 37 |\n| BM_tbb/128/100000000/real_time | 19391815.95 | ns | 35 |\n| BM_omp/4/1000000/real_time | 21915258.37 | ns | 32 |\n| BM_tbb/96/100000000/real_time | 21983605.00 | ns | 30 |\n| BM_async/4/1000000/real_time | 23137887.26 | ns | 30 |\n| BM_dispenso/4/1000000/real_time | 23582652.21 | ns | 29 |\n| BM_tbb/2/1000000/real_time | 25771252.88 | ns | 27 |\n| BM_async/48/100/real_time | 27322856.65 | ns | 100 |\n| BM_tbb/64/100000000/real_time | 27888176.96 | ns | 26 |\n| BM_omp/3/1000000/real_time | 28351498.92 | ns | 25 |\n| BM_dispenso/3/1000000/real_time | 28460979.07 | ns | 24 |\n| BM_async/96/1000000/real_time | 29601378.34 | ns | 139 |\n| BM_async/64/1000000/real_time | 30092573.89 | ns | 100 |\n| BM_async/3/1000000/real_time | 30301994.28 | ns | 23 |\n| BM_async/32/1000000/real_time | 32247921.71 | ns | 22 |\n| BM_tbb/48/100000000/real_time | 33553121.88 | ns | 21 |\n| BM_omp/2/1000000/real_time | 42140655.11 | ns | 17 |\n| BM_dispenso/2/1000000/real_time | 42251319.39 | ns | 16 |\n| BM_async/2/1000000/real_time | 43768641.07 | ns | 16 |\n| BM_async/48/1000000/real_time | 46437838.52 | ns | 53 |\n| BM_serial<kMediumSize> | 48910807.95 | ns | 14 |\n| BM_tbb/32/100000000/real_time | 49079472.57 | ns | 15 |\n| BM_omp/1/1000000/real_time | 49177274.24 | ns | 14 |\n| BM_dispenso/1/1000000/real_time | 49955604.74 | ns | 13 |\n| BM_tbb/1/1000000/real_time | 50727081.27 | ns | 13 |\n| BM_async/1/1000000/real_time | 51434219.31 | ns | 13 |\n| BM_dispenso/192/100000000/real_time | 51876360.28 | ns | 14 |\n| BM_dispenso/128/100000000/real_time | 54079765.61 | ns | 12 |\n| BM_async/128/1000000/real_time | 54664902.58 | ns | 10 |\n| BM_omp/128/100000000/real_time | 55953454.69 | ns | 12 |\n| BM_omp/192/100000000/real_time | 56427148.82 | ns | 13 |\n| BM_dispenso/96/100000000/real_time | 57355264.98 | ns | 12 |\n| BM_omp/96/100000000/real_time | 58653257.48 | ns | 12 |\n| BM_async/64/100/real_time | 59718983.81 | ns | 10 |\n| BM_async/96/100/real_time | 59727838.26 | ns | 10 |\n| BM_tbb/24/100000000/real_time | 61510674.49 | ns | 11 |\n| BM_dispenso/64/100000000/real_time | 62353394.77 | ns | 12 |\n| BM_omp/64/100000000/real_time | 64967464.82 | ns | 11 |\n| BM_async/96/100000000/real_time | 65399402.44 | ns | 12 |\n| BM_async/64/100000000/real_time | 66466260.52 | ns | 10 |\n| BM_dispenso/48/100000000/real_time | 68898697.01 | ns | 10 |\n| BM_omp/48/100000000/real_time | 70999625.33 | ns | 10 |\n| BM_async/48/100000000/real_time | 71698353.81 | ns | 10 |\n| BM_async/128/100000000/real_time | 74639292.74 | ns | 12 |\n| BM_dispenso/32/100000000/real_time | 82606205.25 | ns | 8 |\n| BM_omp/32/100000000/real_time | 83087452.45 | ns | 8 |\n| BM_async/32/100000000/real_time | 84679161.20 | ns | 8 |\n| BM_async/192/100000000/real_time | 87922954.65 | ns | 13 |\n| BM_tbb/16/100000000/real_time | 90113946.94 | ns | 8 |\n| BM_omp/24/100000000/real_time | 98399825.39 | ns | 7 |\n| BM_dispenso/24/100000000/real_time | 98741537.23 | ns | 7 |\n| BM_async/24/100000000/real_time | 112120460.98 | ns | 7 |\n| BM_async/192/100/real_time | 114132438.39 | ns | 7 |\n| BM_async/128/100/real_time | 114184780.05 | ns | 7 |\n| BM_tbb/12/100000000/real_time | 120064682.64 | ns | 6 |\n| BM_async/16/100000000/real_time | 127706208.83 | ns | 5 |\n| BM_omp/16/100000000/real_time | 127790067.03 | ns | 6 |\n| BM_dispenso/16/100000000/real_time | 130645806.71 | ns | 5 |\n| BM_dispenso/12/100000000/real_time | 155060677.79 | ns | 4 |\n| BM_omp/12/100000000/real_time | 156344060.60 | ns | 5 |\n| BM_async/12/100000000/real_time | 158928237.86 | ns | 4 |\n| BM_async/192/1000000/real_time | 177043110.13 | ns | 24 |\n| BM_tbb/8/100000000/real_time | 180690332.78 | ns | 4 |\n| BM_omp/8/100000000/real_time | 215596551.08 | ns | 3 |\n| BM_dispenso/8/100000000/real_time | 219137648.74 | ns | 3 |\n| BM_tbb/6/100000000/real_time | 242198452.35 | ns | 3 |\n| BM_async/8/100000000/real_time | 246772854.28 | ns | 3 |\n| BM_omp/6/100000000/real_time | 270700647.81 | ns | 3 |\n| BM_async/6/100000000/real_time | 275211435.74 | ns | 2 |\n| BM_dispenso/6/100000000/real_time | 275489009.92 | ns | 3 |\n| BM_tbb/4/100000000/real_time | 357043978.76 | ns | 2 |\n| BM_dispenso/4/100000000/real_time | 376902008.43 | ns | 2 |\n| BM_omp/4/100000000/real_time | 385768802.84 | ns | 2 |\n| BM_async/4/100000000/real_time | 388617282.73 | ns | 2 |\n| BM_tbb/3/100000000/real_time | 470701330.34 | ns | 2 |\n| BM_dispenso/3/100000000/real_time | 491667879.75 | ns | 2 |\n| BM_omp/3/100000000/real_time | 499298052.86 | ns | 2 |\n| BM_async/3/100000000/real_time | 509331287.82 | ns | 1 |\n| BM_async/2/100000000/real_time | 712217599.15 | ns | 1 |\n| BM_dispenso/2/100000000/real_time | 712662089.62 | ns | 1 |\n| BM_tbb/2/100000000/real_time | 716891551.39 | ns | 1 |\n| BM_omp/2/100000000/real_time | 721065256.74 | ns | 1 |\n| BM_dispenso/1/100000000/real_time | 1349818846.21 | ns | 1 |\n| BM_async/1/100000000/real_time | 1357735339.55 | ns | 1 |\n| BM_serial<kLargeSize> | 1365698352.46 | ns | 1 |\n| BM_tbb/1/100000000/real_time | 1372401630.51 | ns | 1 |\n| BM_omp/1/100000000/real_time | 1373702608.05 | ns | 1 |\n"
  },
  {
    "path": "docs/building.md",
    "content": "# Building Dispenso\n\nDispenso uses CMake as its build system for open-source builds. Internally at Meta, the Buck\nbuild system is used, but Buck build files are not shipped externally.\n\nImprovements to the CMake build and build files for additional build systems are welcome, as\nare instructions for building on other platforms (BSD variants, Windows+Clang, etc).\n\n## Prerequisites\n\n### CMake\n\n#### Fedora/RPM-based distros\n```bash\nsudo dnf install cmake\n```\n\n#### macOS\n```bash\nbrew install cmake\n```\n\n#### Windows\nInstall CMake from <https://cmake.org/download/>\n\n## Building the Library\n\n### Linux and macOS\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT\nmake -j\n```\n\n### Windows\nAll commands should be run from the Developer Command Prompt (install Build Tools for\nVisual Studio).\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT\ncmake --build . --config Release\n```\n\n## Installing\n\nOnce built, install by building the \"install\" target:\n\n**Linux and macOS:**\n```bash\nmake install\n```\n\n**Windows (also works on any platform):**\n```bash\ncmake --build . --target install\n```\n\n## Using an Installed Dispenso\n\nA downstream CMake project can be pointed to an installed dispenso by using\n`CMAKE_PREFIX_PATH` or `Dispenso_DIR`, either as an environment variable or CMake\nvariable. All that is required is to link the imported CMake target `Dispenso::dispenso`:\n\n```cmake\nfind_package(Dispenso REQUIRED)\ntarget_link_libraries(myDispensoApp Dispenso::dispenso)\n```\n\nThis brings in all required include paths, library files to link, and any other properties\nto the `myDispensoApp` target.\n\n## Testing\n\nTests are not built by default to keep dependencies minimal. Building tests requires\n[GoogleTest](https://github.com/google/googletest).\n\n### Linux and macOS\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT -DDISPENSO_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release\nmake -j\nctest\n```\n\n### Windows\nAll commands should be run from the Developer Command Prompt.\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT -DDISPENSO_BUILD_TESTS=ON\ncmake --build . --config Release\nctest\n```\n\n## Benchmarking\n\nDispenso has several benchmarks that can optionally benchmark against OpenMP, TBB, and/or\nFolly. When benchmarks are enabled via `-DDISPENSO_BUILD_BENCHMARKS=ON`, the build will\nattempt to find these libraries and enable their variants if found. None of these are\ndependencies of the dispenso library itself — only the benchmark binaries.\n\nThe Folly variant is off by default due to common build issues across Folly releases.\nHowever, the Folly benchmarks do run successfully on Meta's internal platform.\n\nOpenMP should already be available on most platforms that support it. TBB can be installed\nvia e.g. `sudo dnf install tbb-devel`.\n\n### Linux and macOS\n```bash\nmkdir build && cd build\ncmake PATH_TO_DISPENSO_ROOT -DDISPENSO_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release\nmake -j\nbin/once_function_benchmark  # example benchmark\n```\n\n### Windows\nNot currently supported through CMake.\n"
  },
  {
    "path": "docs/custom.css",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/* Dispenso custom styling for doxygen-awesome theme */\n\n/* Dispenso green accent in dark mode */\nhtml.dark-mode {\n    --primary-color: #4caf50;\n    --primary-dark-color: #388e3c;\n    --primary-light-color: #81c784;\n}\n\n/* Dispenso green accent in light mode */\nhtml:not(.dark-mode) {\n    --primary-color: #2e7d32;\n    --primary-dark-color: #1b5e20;\n    --primary-light-color: #4caf50;\n}\n"
  },
  {
    "path": "docs/design/barrier_dispatch.md",
    "content": "# Barrier-based Static Dispatch\n\n## Problem\n\nFor memory-bound workloads with small per-chunk compute (e.g. repeated stencil\nover large arrays), dispenso's task-based dispatch is ~2x slower than OpenMP's\n`schedule(static)`. TBB shows the same gap -- this is inherent to task-queue\ndispatch vs fork-join, not a dispenso-specific issue.\n\nThe overhead comes from:\n- Closure packaging (OnceFunction allocation + type erasure)\n- Concurrent queue enqueue/dequeue (CAS operations per task)\n- Per-task atomic counter updates (outstandingTaskCount_)\n- Polling-based wait vs optimized barrier synchronization\n\n### Benchmark evidence (locality_benchmark, 166 HW threads)\n\nRepeated 3-point stencil, 10 passes, 32M doubles (~256MB per array):\n\n| Threads | OMP (static) | TBB | dispenso (kStatic) | dispenso (kAuto) |\n|---------|-------------|------|-------------------|-----------------|\n| 1       | 294ms       | 292ms | 287ms             | 281ms           |\n| 4       | 75ms        | 104ms | 123ms             | 112ms           |\n| 16      | 48ms        | 49ms  | 77ms              | 62ms            |\n| 64      | 32ms        | 56ms  | 57ms              | 56ms            |\n| 128     | 29ms        | 55ms  | 62ms              | 53ms            |\n\nAt 1 thread all four are equivalent, confirming the gap is purely dispatch\noverhead at scale.\n\nThe effect is even more dramatic at smaller sizes where per-chunk work is\ntiny (100K elements, 128 threads: OMP 491us vs dispenso_static 466us vs\ndispenso_auto 1030us).\n\n## Current dispatch path\n\n```\nparallel_for(kStatic) ->\n  for each chunk:\n    1. packageTask: wrap lambda in OnceFunction, atomic++ outstandingTaskCount_\n    2. enqueue: CAS into moodycamel::ConcurrentQueue\n    3. conditionallyWake: atomic read numSleeping_, epoch signal\n  worker thread:\n    4. try_dequeue: CAS from ConcurrentQueue\n    5. execute closure via virtual dispatch (OnceCallable::run)\n    6. atomic-- workRemaining_ (batched per 8)\n  wait:\n    7. poll outstandingTaskCount_ + steal from queue\n```\n\nEach chunk goes through steps 1-7. With 128 chunks x 10 passes = 1280\nround-trips, each involving multiple cache-line-bouncing atomics across\n128 cores.\n\n## Proposed design: broadcast dispatch\n\nFor `parallel_for` with `kStatic` chunking, bypass the general task queue\nand use a lightweight barrier-based dispatch.\n\n### Data structures\n\n```cpp\n// Shared broadcast descriptor -- one per ThreadPool\nstruct BroadcastWork {\n    void (*func)(size_t begin, size_t end, void* ctx);  // static trampoline\n    void* ctx;                                           // captured state\n    size_t total;                                        // total range size\n    ssize_t numParticipants;                             // threads participating\n    std::atomic<int> epoch{0};                           // signals new work\n    std::atomic<int> completionCount{0};                 // barrier counter\n    std::atomic<bool> claimed{false};                    // single-producer lock\n};\n```\n\n### Dispatch path (parallel_for_staticImpl fast path)\n\n```\nparallel_for(kStatic) ->\n  if nested (isPoolRecursive): fall back to normal task-queue path\n  if !broadcast.claimed.exchange(true): fall back to normal path\n  1. Write func, ctx, total, numParticipants to broadcast struct\n  2. release fence\n  3. epoch.fetch_add(1)             // single atomic -- signals all threads\n  4. wakeN(sleeping)                // reuse existing mechanism\n  5. Execute own chunk (tid=0) inline\n  6. Spin on completionCount == numParticipants  (+ steal from general queue)\n  7. Reset completionCount, release claimed\n```\n\n### Thread loop integration\n\n```cpp\nvoid ThreadPool::threadLoop(PerThreadData& data) {\n    int lastEpoch = broadcast_.epoch.load(acquire);\n    while (data.running()) {\n        // Priority check: broadcast work available?\n        int curEpoch = broadcast_.epoch.load(acquire);\n        if (curEpoch != lastEpoch) {\n            lastEpoch = curEpoch;\n            // Compute own chunk arithmetically -- zero overhead\n            size_t begin = (broadcast_.total * myTid) / broadcast_.numParticipants;\n            size_t end = (broadcast_.total * (myTid + 1)) / broadcast_.numParticipants;\n            broadcast_.func(begin, end, broadcast_.ctx);  // direct call\n            broadcast_.completionCount.fetch_add(1, release);\n            continue;  // re-check for more broadcast work\n        }\n        // Normal path: dequeue from general queue\n        // ... existing try_dequeue logic ...\n    }\n}\n```\n\n### Type erasure without virtual dispatch\n\nThe broadcast function pointer uses a C-style `void(*)(size_t, size_t, void*)`\ntrampoline. `parallel_for` generates this at compile time:\n\n```cpp\ntemplate <typename F>\nvoid parallel_for_broadcast(TaskSet& tasks, size_t begin, size_t end, F&& f) {\n    struct Ctx { F* func; };\n    Ctx ctx{&f};\n    auto trampoline = [](size_t b, size_t e, void* raw) {\n        auto* c = static_cast<Ctx*>(raw);\n        (*c->func)(b, e);\n    };\n    pool.broadcastDispatch(trampoline, &ctx, end - begin);\n}\n```\n\nNo OnceFunction, no allocation, no virtual dispatch. The trampoline is a\nstatic function instantiated per call site.\n\n### Nested parallelism\n\nDo NOT use broadcast path when `PerPoolPerThreadInfo::isPoolRecursive(this)`\nis true. Inner parallel_for would try to broadcast, but outer parallel_for's\nthreads are busy executing their outer chunks and won't service the broadcast.\nThis would deadlock.\n\nFall back to normal task-queue dispatch for nested cases. The existing\nwork-stealing in `wait()` handles this correctly.\n\n### Concurrency with general tasks\n\nThe broadcast path is single-producer: only one parallel_for can use it at a\ntime. `claimed` is an atomic flag used as a try-lock:\n\n```cpp\nif (!broadcast_.claimed.exchange(true, acquire)) {\n    // Someone else is using broadcast -- fall back to task queue\n    return normal_dispatch(tasks, ...);\n}\n// ... do broadcast dispatch ...\nbroadcast_.claimed.store(false, release);\n```\n\nThis keeps the optimization opportunistic. In the common case (single\nparallel_for at a time, no nesting), it fires. When contended, it falls\nback gracefully.\n\n### Interaction with TaskSet wait/steal\n\nThe calling thread's `wait()` must still steal from the general queue while\nwaiting for broadcast completion. This prevents deadlock when broadcast\nparallel_for is mixed with other queued work:\n\n```cpp\n// Caller after dispatching broadcast and executing own chunk:\nwhile (broadcast_.completionCount.load(acquire) < numParticipants - 1) {\n    pool.tryExecuteNext();  // steal general queue work\n    // ... backoff ...\n}\n```\n\n### Thread ID assignment\n\nEach pool thread needs a stable `tid` for computing its chunk bounds. Options:\n- Use the existing `PerPoolPerThreadInfo` thread-local registration to assign\n  sequential IDs at thread creation\n- Store tid in `PerThreadData` (already exists, just add an index field)\n\nThe caller (master thread) always takes tid=0.\n\n## Expected impact\n\nShould bring kStatic parallel_for close to OMP for regular, memory-bound\nworkloads. Per-dispatch overhead drops from O(numChunks) atomic operations\nto O(1) (single epoch bump + barrier).\n\nThe remaining gap vs OMP would be:\n- Barrier quality (OMP uses architecture-specific tree/butterfly barriers;\n  we'd start with a simple atomic counter)\n- Thread affinity (OMP runtimes pin threads to cores; dispenso doesn't)\n- The epoch check in threadLoop adds one atomic load to every dequeue\n  iteration (should be negligible -- same cache line, read-only when idle)\n\n## Risks and open questions\n\n- **Complexity**: Dual dispatch in threadLoop must not regress the common\n  task-queue path. The epoch check is a single relaxed atomic load, but\n  code complexity increases.\n- **Fairness**: If broadcast work keeps arriving, general queue tasks could\n  starve. May need a fairness counter (check general queue every N broadcast\n  rounds, or after each broadcast completion).\n- **Memory ordering**: The broadcast struct write must be visible before the\n  epoch bump. A release fence between writing func/ctx/total and incrementing\n  epoch suffices.\n- **Thread count mismatch**: If some pool threads are sleeping and don't wake\n  in time, the barrier would hang. Need a timeout or adaptive participant\n  count based on actually-awake threads.\n- **Partial pool usage**: If the user's TaskSet uses a subset of the pool's\n  threads (via stealingLoadMultiplier), broadcast must respect this.\n\n## Validation\n\nlocality_benchmark already exists and covers the target workload. Success\ncriteria: dispenso_static within 1.5x of OMP at 64-128 threads for the\n32M stencil case (currently 2x).\n"
  },
  {
    "path": "docs/design/coroutines.md",
    "content": "# Dispenso Coroutine Support Design Document\n\n## Overview\n\nThis document outlines the design for C++20 coroutine integration with dispenso. The goal is to\nallow coroutines to run on dispenso's thread pool infrastructure, enabling ergonomic async\nprogramming while leveraging dispenso's work stealing and nested parallelism capabilities.\n\n## Requirements\n\n**C++20 Required**: This feature requires C++20 coroutine support. We will not backport\ncoroutine machinery to C++14/C++17.\n\n```cpp\n#if defined(__cpp_impl_coroutine) && __cpp_impl_coroutine >= 201902L\n#define DISPENSO_HAS_COROUTINES 1\n#include <coroutine>\n#endif\n```\n\n## Motivation\n\nTraditional async patterns with dispenso:\n\n```cpp\n// Blocking: ties up a thread at each .get()\nFuture<int> f1 = async(pool, work1);\nint a = f1.get();  // Thread blocked waiting\nFuture<int> f2 = async(pool, work2);\nint b = f2.get();  // Thread blocked again\n```\n\nWith coroutines:\n\n```cpp\n// Non-blocking: coroutine suspends, thread is freed\nTask<int> example() {\n    int a = co_await async(pool, work1);  // Suspends, thread freed\n    int b = co_await async(pool, work2);  // Suspends, thread freed\n    co_return a + b;\n}\n```\n\nBenefits:\n1. **Thread efficiency** - Suspended coroutines don't block threads\n2. **Composability** - Chain async operations naturally with sequential-looking code\n3. **Integration** - Works with dispenso's thread pools and work stealing\n\n## Design Goals\n\n1. **Lazy tasks** - Coroutines don't start until awaited or explicitly spawned\n2. **Inline resumption by default** - Minimize scheduling overhead for compute workloads\n3. **Explicit redistribution** - Users can fan out work to the pool when parallelism is needed\n4. **I/O thread isolation** - I/O completions dispatch to compute pool, not inline\n5. **Work stealing compatibility** - Scheduled continuations participate in work stealing\n\n## Core Concepts\n\n### Task<T>\n\nA lazy coroutine return type representing async work that produces a value of type `T`.\n\n```cpp\nnamespace dispenso {\n\ntemplate<typename T = void>\nclass Task {\n public:\n  using promise_type = /* implementation defined */;\n\n  // Not copyable\n  Task(const Task&) = delete;\n  Task& operator=(const Task&) = delete;\n\n  // Movable\n  Task(Task&& other) noexcept;\n  Task& operator=(Task&& other) noexcept;\n\n  // Awaitable\n  auto operator co_await() && -> /* awaiter */;\n\n  // Check if task holds a valid coroutine\n  explicit operator bool() const noexcept;\n};\n\n}  // namespace dispenso\n```\n\n**Lazy semantics**: Calling a coroutine function returns a `Task` immediately without\nexecuting any code. Execution begins when the task is awaited.\n\n```cpp\nTask<int> compute() {\n    std::cout << \"Starting\\n\";  // NOT printed until awaited\n    co_return 42;\n}\n\nTask<int> t = compute();  // Nothing printed yet\nint x = co_await t;       // NOW \"Starting\" is printed\n```\n\n### schedule_on\n\nSuspend the current coroutine and resume on a thread pool.\n\n```cpp\nnamespace dispenso {\n\nauto schedule_on(ThreadPool& pool) -> /* awaitable */;\n\n// Convenience: use global thread pool\nauto schedule_on() -> /* awaitable */;\n\n}  // namespace dispenso\n```\n\nUsage:\n\n```cpp\nTask<void> example() {\n    // Running on some thread (maybe main)\n    co_await schedule_on(pool);\n    // Now running on a pool thread\n    do_compute_work();\n}\n```\n\nThis is an explicit redistribution point - useful when you want to move execution to\nthe pool or yield to allow other work to run.\n\n### Awaitable Future<T>\n\nMake `dispenso::Future<T>` directly awaitable.\n\n```cpp\nnamespace dispenso {\n\ntemplate<typename T>\nauto operator co_await(Future<T>& future) -> /* awaiter */;\n\ntemplate<typename T>\nauto operator co_await(Future<T>&& future) -> /* awaiter */;\n\n}  // namespace dispenso\n```\n\nUsage:\n\n```cpp\nTask<int> example() {\n    Future<int> fut = async(pool, [] { return expensive_compute(); });\n\n    // Do other work while compute runs...\n\n    int result = co_await fut;  // Suspend until future ready\n    co_return result * 2;\n}\n```\n\n## Resume Policies\n\nWhere a coroutine resumes after `co_await` depends on what was awaited:\n\n| Awaitable | Resume Policy | Rationale |\n|-----------|---------------|-----------|\n| `Future<T>` | Inline | Throughput; completing thread continues |\n| `schedule_on(pool)` | On pool | Explicit redistribution request |\n| `spawn_on(pool, task)` | On pool | Child task runs on pool |\n| I/O operations | On compute pool | Keep I/O thread free |\n\n### Inline Resumption\n\nWhen a `Future` completes, the thread that completed it directly resumes the\nwaiting coroutine. This minimizes overhead:\n\n```\nPool Thread P1: [runs future work] -> [resumes coroutine] -> [continues coroutine]\n```\n\nNo scheduling, no context switch - maximum throughput for compute-bound chains.\n\n### Pool Resumption\n\nWhen explicit redistribution is needed, the continuation is scheduled as new work:\n\n```\nThread X: [completes operation] -> [schedules continuation on pool]\nPool Thread P2: [picks up continuation] -> [resumes coroutine]\n```\n\nThis integrates with dispenso's work stealing - if the pool is saturated, the\nscheduling thread may execute the continuation inline (preventing deadlock).\n\n## Parallelism Primitives\n\n### spawn_on\n\nStart a task on a thread pool, returning a handle to await later.\n\n```cpp\nnamespace dispenso {\n\ntemplate<typename T>\nTask<T> spawn_on(ThreadPool& pool, Task<T> task);\n\n// Convenience: use global thread pool\ntemplate<typename T>\nTask<T> spawn_on(Task<T> task);\n\n}  // namespace dispenso\n```\n\nUsage:\n\n```cpp\nTask<void> parallel_work() {\n    // Fan out: start tasks on pool\n    Task<int> a = spawn_on(pool, compute_a());\n    Task<int> b = spawn_on(pool, compute_b());\n\n    // Both running concurrently on pool threads\n\n    // Fan in: await results\n    int result_a = co_await a;\n    int result_b = co_await b;\n\n    co_return;\n}\n```\n\n### when_all\n\nAwait multiple tasks concurrently, returning when all complete.\n\n```cpp\nnamespace dispenso {\n\ntemplate<typename... Tasks>\nTask<std::tuple</* result types */>> when_all(Tasks&&... tasks);\n\ntemplate<typename T>\nTask<std::vector<T>> when_all(std::vector<Task<T>> tasks);\n\n}  // namespace dispenso\n```\n\nUsage:\n\n```cpp\nTask<void> process_all(std::vector<Item>& items) {\n    std::vector<Task<Result>> tasks;\n    for (auto& item : items) {\n        tasks.push_back(spawn_on(pool, process(item)));\n    }\n\n    std::vector<Result> results = co_await when_all(std::move(tasks));\n}\n```\n\n### when_any (Future)\n\nAwait multiple tasks, returning when the first completes. Lower priority than `when_all`.\n\n## Blocking Wait\n\nFor integration with non-coroutine code, provide a way to block until a task completes.\n\n```cpp\nnamespace dispenso {\n\ntemplate<typename T>\nT sync_wait(Task<T> task);\n\ntemplate<typename T>\nT sync_wait(Task<T> task, ThreadPool& pool);\n\n}  // namespace dispenso\n```\n\nUsage:\n\n```cpp\nint main() {\n    Task<int> t = async_computation();\n    int result = sync_wait(std::move(t));  // Block main thread until done\n    std::cout << result << \"\\n\";\n}\n```\n\n## I/O Integration (Future Phase)\n\nFor high-performance async I/O, we would add an `IoContext` that manages platform-native\nasync I/O and dispatches completions to the compute pool.\n\n### Architecture\n\n```\n                    ┌─────────────────┐\n                    │  Compute Pool   │\n                    │  (N threads)    │\n                    └────────▲────────┘\n                             │ schedule resumption\n                    ┌────────┴────────┐\n                    │   I/O Thread    │\n                    │  (1-2 threads)  │\n                    └────────▲────────┘\n                             │ completion events\n                    ┌────────┴────────┐\n                    │     Kernel      │\n                    │ io_uring/kqueue │\n                    │     /IOCP       │\n                    └─────────────────┘\n```\n\nThe I/O thread:\n1. Submits I/O requests to the kernel\n2. Waits for completions (blocking on io_uring/kqueue/IOCP)\n3. For each completion, schedules the coroutine resumption on the compute pool\n4. Never runs compute work itself\n\n### Platform Backends\n\n| Platform | Backend | Notes |\n|----------|---------|-------|\n| Linux | io_uring | Kernel 5.1+, best performance |\n| Linux (fallback) | epoll | Older kernels |\n| macOS | kqueue | Native async events |\n| Windows | IOCP | Overlapped I/O |\n\n### API Sketch\n\n```cpp\nnamespace dispenso::io {\n\nclass IoContext {\n public:\n  explicit IoContext(ThreadPool& compute_pool);\n\n  // Start the I/O thread\n  void run();\n\n  // Stop the I/O thread\n  void stop();\n};\n\n// File operations\nTask<std::vector<std::byte>> read_file(IoContext& ctx, const fs::path& path);\nTask<void> write_file(IoContext& ctx, const fs::path& path, std::span<const std::byte> data);\n\n// Potentially: sockets, timers, etc.\n\n}  // namespace dispenso::io\n```\n\n## Error Handling\n\nExceptions thrown in coroutines are captured and rethrown when the task is awaited:\n\n```cpp\nTask<int> failing_task() {\n    co_await schedule_on(pool);\n    throw std::runtime_error(\"oops\");\n    co_return 42;  // Never reached\n}\n\nTask<void> caller() {\n    try {\n        int x = co_await failing_task();\n    } catch (const std::runtime_error& e) {\n        // Exception caught here\n    }\n}\n```\n\n## Cancellation (Future Consideration)\n\nPotential integration with `std::stop_token` for cooperative cancellation:\n\n```cpp\nTask<int> cancellable_work(std::stop_token token) {\n    for (int i = 0; i < 1000; ++i) {\n        if (token.stop_requested()) {\n            co_return -1;  // Early exit\n        }\n        co_await process_chunk(i);\n    }\n    co_return 0;\n}\n```\n\nThis is deferred to a future phase.\n\n## Performance Considerations\n\n### Coroutine Frame Allocation\n\nCoroutine frames are typically heap-allocated. For performance-critical code:\n\n1. **HALO (Heap Allocation eLision Optimization)** - Compilers can elide allocation\n   when the coroutine lifetime is bounded by the caller\n2. **Custom allocators** - `promise_type` can define `operator new` for custom allocation\n3. **Frame pooling** - Reuse coroutine frames for frequently-created coroutines\n\n### Symmetric Transfer\n\nC++20 supports symmetric transfer via `await_suspend` returning a `coroutine_handle<>`.\nThis allows direct transfer between coroutines without growing the call stack:\n\n```cpp\nauto await_suspend(std::coroutine_handle<> h) -> std::coroutine_handle<> {\n    // Instead of: h.resume(); return;\n    // Return the handle to transfer to:\n    return continuation_;  // Direct transfer, no stack growth\n}\n```\n\nWe should use symmetric transfer where applicable to prevent stack overflow in\ndeep coroutine chains.\n\n### Comparison with std::execution::par\n\n| Aspect | Coroutines | parallel_for |\n|--------|------------|--------------|\n| Overhead per operation | ~50-100ns (allocation) | ~10-20ns |\n| Best for | I/O, async chains, latency | Compute, throughput |\n| Thread blocking | Never | Never |\n| Code style | Sequential-looking async | Explicit parallelism |\n\nUse coroutines for async workflows; use `parallel_for` for data parallelism.\n\n## Header Organization\n\n```\ndispenso/\n├── coroutine.h              // Main header, includes all coroutine support\n├── coroutine/\n│   ├── task.h               // Task<T> definition\n│   ├── schedule.h           // schedule_on, spawn_on\n│   ├── sync_wait.h          // sync_wait for blocking\n│   ├── when_all.h           // when_all combinator\n│   └── future_awaitable.h   // operator co_await for Future<T>\n└── io/                      // Future phase\n    ├── io_context.h         // IoContext\n    └── file.h               // File operations\n```\n\n## Implementation Phases\n\n### Phase 1: Core Primitives\n\n1. `Task<T>` with lazy semantics\n2. `schedule_on(ThreadPool&)`\n3. `sync_wait(Task<T>)`\n4. Awaitable `Future<T>`\n\n### Phase 2: Parallelism Combinators\n\n1. `spawn_on(ThreadPool&, Task<T>)`\n2. `when_all(Tasks...)`\n3. `when_all(vector<Task<T>>)`\n\n### Phase 3: I/O (Optional/Future)\n\n1. `IoContext` with platform backends\n2. File read/write operations\n3. Potential: sockets, timers\n\n## Testing Strategy\n\nEach component should have tests for:\n\n1. **Basic functionality** - Happy path execution\n2. **Exception propagation** - Errors caught at await point\n3. **Cancellation** - Coroutine destroyed before completion\n4. **Thread safety** - Concurrent await, spawn, etc.\n5. **Work stealing interaction** - Behavior under pool saturation\n6. **Nested coroutines** - Coroutines spawning coroutines\n7. **Memory** - No leaks, proper frame destruction\n\n## Open Questions\n\n1. **Naming**: `spawn_on` vs `start_on` vs `dispatch`?\n\n2. **Default pool**: Should `schedule_on()` (no args) use a global pool, or require explicit pool?\n   Recommendation: Require explicit pool for clarity, but could add a thread-local \"current pool\" concept.\n\n3. **Task move semantics**: Should awaiting a Task consume it (require `co_await std::move(t)`)?\n   Recommendation: Yes, prevents accidental double-await.\n\n4. **Integration with dispenso::Future**: Should `Task<T>` be convertible to `Future<T>`?\n   This would allow mixing coroutine and callback-based code.\n\n5. **Allocator support**: Should `Task` support custom allocators for frame allocation?\n   Recommendation: Defer to later phase; standard allocation is usually fine.\n\n## References\n\n- [C++20 Coroutines](https://en.cppreference.com/w/cpp/language/coroutines)\n- [Lewis Baker's Coroutine Theory](https://lewissbaker.github.io/)\n- [cppcoro Library](https://github.com/lewissbaker/cppcoro)\n- [libcoro Library](https://github.com/jbaldwin/libcoro)\n- [concurrencpp Library](https://github.com/David-Haim/concurrencpp)\n- [libfork Library](https://github.com/ConorWilliams/libfork)\n- [libunifex](https://github.com/facebookexperimental/libunifex)\n- [io_uring](https://kernel.dk/io_uring.pdf)\n\n## Existing Libraries Analysis\n\nWe surveyed existing C++ coroutine libraries to inform our design decisions.\n\n### Library Comparison\n\n| Library | C++ Version | Task Pattern | Thread Pool | Work Stealing | I/O Support | License |\n|---------|-------------|--------------|-------------|---------------|-------------|---------|\n| cppcoro | C++17 (experimental) | Lazy, symmetric transfer | static_thread_pool | Yes | io_service | MIT |\n| libcoro | C++20 | Lazy, symmetric transfer | thread_pool | No (FIFO) | io_scheduler | MIT |\n| concurrencpp | C++20 | Executor-based | Multiple types | No | No | MIT |\n| libfork | C++20 | Fork-join focused | busy_pool, lazy_pool | Yes (NUMA-aware) | No | MPL-2.0 |\n\n### Key Patterns to Adopt\n\n**From cppcoro (Lewis Baker - designer of C++ coroutines):**\n\n1. **Lazy Task semantics** - `initial_suspend()` returns `suspend_always`\n2. **Symmetric transfer** - `await_suspend` returns `coroutine_handle<>` for stack-safe chaining\n3. **final_awaitable pattern** - Continuation chaining without scheduler overhead\n\n```cpp\n// Pattern from cppcoro - final_awaitable for inline continuation\nstruct final_awaitable {\n    bool await_ready() const noexcept { return false; }\n\n    std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h) noexcept {\n        // Symmetric transfer to continuation - no stack growth\n        return h.promise().m_continuation;\n    }\n\n    void await_resume() noexcept {}\n};\n```\n\n**From libcoro (modern C++20 reference):**\n\n1. **Clean C++20 implementation** - Uses `<coroutine>` header (not experimental)\n2. **std::variant for result storage** - Type-safe value/exception storage\n3. **schedule_operation pattern** - Awaitable type for thread pool scheduling\n\n### Why Not Depend on an Existing Library\n\n1. **dispenso already has a superior ThreadPool** - Our work-stealing implementation is\n   battle-tested and optimized. Adding cppcoro/libcoro would duplicate or conflict.\n\n2. **Thin integration layer** - The core Task machinery is ~300-400 lines. We can adopt\n   the patterns without taking a dependency.\n\n3. **Control over resume policy** - We need fine-grained control over inline vs pool\n   resumption to integrate with dispenso's work stealing.\n\n4. **Licensing simplicity** - Keeping implementation in-house avoids license management.\n\n### Implementation Approach\n\n1. **Task<T>**: Adapt the cppcoro/libcoro pattern (lazy, symmetric transfer, final_awaitable)\n2. **schedule_on**: Create awaitable that schedules continuation on dispenso::ThreadPool\n3. **Awaitable Future<T>**: Wrap dispenso::Future with coroutine await interface\n4. **when_all**: Reference libcoro's implementation for clean variadic/vector patterns\n\n## Testing Strategy\n\nEach component should have tests for:\n\n1. **Basic functionality** - Happy path execution\n2. **Exception propagation** - Errors caught at await point\n3. **Cancellation** - Coroutine destroyed before completion\n4. **Thread safety** - Concurrent await, spawn, etc.\n5. **Work stealing interaction** - Behavior under pool saturation\n6. **Nested coroutines** - Coroutines spawning coroutines\n7. **Memory** - No leaks, proper frame destruction\n\n### Test Categories\n\n| Component | Test Coverage |\n|-----------|---------------|\n| `Task<T>` | Construction, move, await, exception, void specialization, reference types |\n| `Task<void>` | Return void, exception propagation |\n| `schedule_on` | Switch threads, work stealing under load, nested scheduling |\n| `sync_wait` | Block until complete, exception propagation, timeout |\n| `spawn_on` | Concurrent execution, result collection |\n| `when_all` | Variadic, vector, mixed types, partial failure |\n| `Future<T>` awaitable | Already-ready, pending, exception |\n\n## Benchmarking Strategy\n\nWe will benchmark against existing coroutine libraries to validate our implementation\nachieves competitive or superior performance, especially for dispenso's target use cases.\n\n### Benchmark Libraries\n\n- **cppcoro** - Baseline reference implementation\n- **libcoro** - Modern C++20 comparison\n- **libfork** - Work-stealing coroutine comparison\n- **folly::coro** (if available) - Production-grade comparison\n\n### Benchmark Scenarios\n\n| Benchmark | Description | Metrics |\n|-----------|-------------|---------|\n| **Task creation/destruction** | Create and destroy N tasks without execution | ops/sec, memory |\n| **Sequential await chain** | Chain of N co_await operations | latency, throughput |\n| **Fan-out/fan-in** | spawn N tasks, when_all to join | throughput, scalability |\n| **Nested parallelism** | Recursive task spawning (tree structure) | throughput, work stealing efficiency |\n| **Mixed workload** | Combination of short/long tasks | fairness, tail latency |\n| **sync_wait overhead** | Cost of blocking wait vs raw Future::get() | latency comparison |\n| **schedule_on overhead** | Cost of thread switch vs direct pool.schedule() | latency comparison |\n| **Contention** | Many threads spawning tasks concurrently | throughput under contention |\n\n### Key Metrics\n\n1. **Throughput** - Tasks completed per second\n2. **Latency** - Time from spawn to completion (p50, p99, p999)\n3. **Scalability** - Throughput vs thread count\n4. **Memory overhead** - Per-task allocation overhead\n5. **Context switch cost** - schedule_on latency\n\n### Benchmark Implementation\n\n```cpp\n// Example: Fan-out/fan-in benchmark\nvoid BM_FanOutFanIn(benchmark::State& state) {\n    const int num_tasks = state.range(0);\n    dispenso::ThreadPool pool(std::thread::hardware_concurrency());\n\n    for (auto _ : state) {\n        auto result = sync_wait(fan_out_fan_in(pool, num_tasks));\n        benchmark::DoNotOptimize(result);\n    }\n\n    state.SetItemsProcessed(state.iterations() * num_tasks);\n}\nBENCHMARK(BM_FanOutFanIn)->Range(8, 8192);\n```\n\n### Comparison Methodology\n\n1. **Equivalent workloads** - Same task logic across libraries\n2. **Same hardware** - All benchmarks on identical machines\n3. **Warm-up** - Discard initial iterations for JIT/cache effects\n4. **Statistical rigor** - Multiple runs, report mean/stddev\n5. **Profile-guided analysis** - Use perf/vtune to understand bottlenecks\n\n## Implementation Checklist\n\nPrimitives in implementation order. Check off as completed.\n\n### Phase 1: Core Primitives\n- [ ] `Task<T>` (lazy coroutine type)\n- [ ] `Task<void>` specialization\n- [ ] `schedule_on(ThreadPool&)`\n- [ ] `sync_wait(Task<T>)`\n- [ ] Awaitable `Future<T>`\n\n### Phase 2: Parallelism Combinators\n- [ ] `spawn_on(ThreadPool&, Task<T>)`\n- [ ] `when_all(Tasks...)` (variadic)\n- [ ] `when_all(vector<Task<T>>)`\n- [ ] `when_any` (optional)\n\n### Phase 3: I/O (Future)\n- [ ] `IoContext` base infrastructure\n- [ ] Linux io_uring backend\n- [ ] Linux epoll fallback\n- [ ] macOS kqueue backend\n- [ ] Windows IOCP backend\n- [ ] `read_file` / `write_file`\n\n### Testing & Benchmarks\n- [ ] Unit tests for all Phase 1 primitives\n- [ ] Unit tests for all Phase 2 combinators\n- [ ] Benchmark: Task creation/destruction\n- [ ] Benchmark: Sequential await chain\n- [ ] Benchmark: Fan-out/fan-in\n- [ ] Benchmark: Nested parallelism\n- [ ] Benchmark: Comparison vs cppcoro\n- [ ] Benchmark: Comparison vs libcoro\n- [ ] Benchmark: Comparison vs libfork\n"
  },
  {
    "path": "docs/design/cpp20_concepts.md",
    "content": "# C++20 Concepts for Dispenso\n\n## Overview\n\nThis document outlines a plan to add C++20 concept constraints to dispenso's template APIs.\nThe goal is to provide better error messages when template requirements are not met, while\nmaintaining full backward compatibility with C++14/17.\n\n## Motivation\n\nCurrent template errors in dispenso can be cryptic. For example, passing a non-callable\nto `parallel_for` produces deep template instantiation errors. With concepts, users get\nclear messages like \"constraint not satisfied: F must be invocable with (size_t, size_t)\".\n\n## Design Principles\n\n1. **Backward compatible** - All code that compiles with C++14/17 continues to work\n2. **Graceful degradation** - Concepts only active when `__cpp_concepts >= 201907L`\n3. **Incremental adoption** - Can add concepts to APIs one at a time\n4. **Documentation value** - Concepts serve as executable documentation of requirements\n\n## Implementation Strategy\n\n### Feature Detection Macro\n\n```cpp\n// In dispenso/platform.h or a new dispenso/concepts.h\n\n#if __cplusplus >= 202002L && defined(__cpp_concepts) && __cpp_concepts >= 201907L\n#define DISPENSO_HAS_CONCEPTS 1\n#else\n#define DISPENSO_HAS_CONCEPTS 0\n#endif\n```\n\n### Concept Definitions\n\n```cpp\n// dispenso/concepts.h (new header)\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n#if DISPENSO_HAS_CONCEPTS\n\n#include <concepts>\n#include <type_traits>\n\nnamespace dispenso {\n\n/// A type that can be invoked with the given arguments\ntemplate<typename F, typename... Args>\nconcept Invocable = std::invocable<F, Args...>;\n\n/// A type that can be invoked and returns a specific type\ntemplate<typename F, typename R, typename... Args>\nconcept InvocableR = std::invocable<F, Args...> &&\n    std::convertible_to<std::invoke_result_t<F, Args...>, R>;\n\n/// A callable suitable for parallel_for with index range\ntemplate<typename F>\nconcept ParallelForCallable = Invocable<F, size_t, size_t>;\n\n/// A callable suitable for parallel_for with single index\ntemplate<typename F>\nconcept ParallelForIndexCallable = Invocable<F, size_t>;\n\n/// A callable suitable for parallel_for with state\ntemplate<typename F, typename State>\nconcept ParallelForStateCallable = Invocable<F, State&, size_t, size_t>;\n\n/// A callable suitable for TaskSet::schedule\ntemplate<typename F>\nconcept TaskCallable = Invocable<F> && std::is_void_v<std::invoke_result_t<F>>;\n\n/// A state factory for parallel_for\ntemplate<typename F, typename State>\nconcept StateFactory = Invocable<F> &&\n    std::convertible_to<std::invoke_result_t<F>, State>;\n\n/// A binary operation for reduce\ntemplate<typename Op, typename T>\nconcept BinaryOp = Invocable<Op, T, T> &&\n    std::convertible_to<std::invoke_result_t<Op, T, T>, T>;\n\n/// Iterator that supports random access (needed for efficient parallel iteration)\ntemplate<typename It>\nconcept RandomAccessIterator = std::random_access_iterator<It>;\n\n/// Iterator that is at least forward (minimum for parallel algorithms)\ntemplate<typename It>\nconcept ForwardIterator = std::forward_iterator<It>;\n\n}  // namespace dispenso\n\n#endif  // DISPENSO_HAS_CONCEPTS\n```\n\n### Applying Concepts to APIs\n\nUse `requires` clauses that are conditionally compiled:\n\n```cpp\n// Example: parallel_for\n\n#if DISPENSO_HAS_CONCEPTS\ntemplate <typename F>\n  requires ParallelForCallable<F>\n#else\ntemplate <typename F>\n#endif\nvoid parallel_for(size_t begin, size_t end, F&& f);\n```\n\nOr use a macro for cleaner syntax:\n\n```cpp\n// In platform.h or concepts.h\n#if DISPENSO_HAS_CONCEPTS\n#define DISPENSO_REQUIRES(...) requires (__VA_ARGS__)\n#else\n#define DISPENSO_REQUIRES(...)\n#endif\n\n// Usage\ntemplate <typename F>\nDISPENSO_REQUIRES(ParallelForCallable<F>)\nvoid parallel_for(size_t begin, size_t end, F&& f);\n```\n\n## Priority APIs for Concept Constraints\n\n### High Priority (Most User-Facing)\n\n| API | Concept Constraint |\n|-----|-------------------|\n| `parallel_for` (all overloads) | `ParallelForCallable`, `ParallelForIndexCallable`, `ParallelForStateCallable` |\n| `TaskSet::schedule` | `TaskCallable` |\n| `Future::then` | `Invocable<F, T>` where T is the Future's value type |\n| `for_each` | `Invocable<F, T&>` where T is the element type |\n| `Pipeline` stage functions | Various invocable constraints |\n\n### Medium Priority\n\n| API | Concept Constraint |\n|-----|-------------------|\n| `Graph` node functions | `TaskCallable` |\n| `ConcurrentVector` operations | Element type constraints |\n| `reduce` (when implemented) | `BinaryOp` |\n\n### Lower Priority\n\n| API | Concept Constraint |\n|-----|-------------------|\n| Allocator APIs | Standard allocator concepts |\n| Internal utilities | Not user-facing, lower value |\n\n## Example Error Messages\n\n### Before (C++17)\n\n```\nerror: no matching function for call to 'parallel_for'\nnote: candidate template ignored: substitution failure [with F = int]:\n      no type named 'type' in 'std::invoke_result<int, unsigned long, unsigned long>'\n```\n\n### After (C++20 with concepts)\n\n```\nerror: constraints not satisfied for 'parallel_for<int>'\nnote: because 'int' does not satisfy 'ParallelForCallable'\nnote: because 'std::invocable<int, size_t, size_t>' evaluated to false\n```\n\n## Testing Strategy\n\n1. **Positive tests** - Verify valid code compiles with concepts enabled\n2. **Negative tests** - Verify invalid code produces expected concept errors (manual verification)\n3. **Cross-version tests** - Same tests pass on C++14, C++17, and C++20\n4. **CI matrix** - Test with multiple compilers (GCC, Clang, MSVC) and standards\n\n## Implementation Phases\n\n### Phase 1: Infrastructure\n- [ ] Add `DISPENSO_HAS_CONCEPTS` macro to platform.h\n- [ ] Create `dispenso/concepts.h` with core concept definitions\n- [ ] Add `DISPENSO_REQUIRES` macro\n\n### Phase 2: Core APIs\n- [ ] `parallel_for` (all overloads)\n- [ ] `TaskSet::schedule`\n- [ ] `for_each`\n\n### Phase 3: Future and Async\n- [ ] `Future::then`\n- [ ] `Future::whenAll`\n- [ ] `async`\n\n### Phase 4: Advanced APIs\n- [ ] `Pipeline` stage functions\n- [ ] `Graph` node functions\n- [ ] Parallel algorithms (as they are implemented)\n\n## Compatibility Notes\n\n- GCC 10+ supports concepts\n- Clang 10+ supports concepts\n- MSVC 19.28+ (VS 2019 16.8+) supports concepts\n- Older compilers will simply not get the concept constraints\n\n## Open Questions\n\n1. Should we provide our own concept definitions or rely on `<concepts>` header?\n   - Recommendation: Define our own in terms of std concepts for customization\n\n2. Should concepts be in a sub-namespace?\n   - Recommendation: No, keep in `dispenso::` for simplicity\n\n3. Should we add concepts to internal/detail APIs?\n   - Recommendation: No, focus on public APIs for maximum user benefit\n"
  },
  {
    "path": "docs/design/fast_math_roadmap.md",
    "content": "# dispenso::fast_math Roadmap\n\nThis document tracks planned features and improvements for the fast_math sublibrary.\n\n## V1 Scope (Current)\n\n### Functions Shipped\n\n| Category | Functions |\n|----------|-----------|\n| Trigonometric | sin, cos, sincos, sinpi, cospi, sincospi, tan, asin, acos, atan, atan2 |\n| Exponential | exp, exp2, exp10, expm1 |\n| Logarithmic | log, log1p, log2, log10 |\n| Hyperbolic | tanh |\n| Power | pow, sqrt, cbrt, hypot |\n| Other | frexp, ldexp |\n\nAll functions are templated on float type and support:\n- Scalar `float`\n- SSE4.1 (`SseFloat` / `__m128`)\n- AVX2 (`AvxFloat` / `__m256`)\n- AVX-512 (`Avx512Float` / `__m512`)\n- NEON/aarch64 (`NeonFloat` / `float32x4_t`)\n- Highway (`HwyFloat` / `hn::Vec<>`)\n\n### V1 TODO\n\n| Task | Status | Notes |\n|------|--------|-------|\n| Complete SIMD benchmark coverage | Done | All functions covered across SSE/AVX/AVX-512/NEON/Highway |\n| Benchmark on Linux x86 | Done | Results recorded in README |\n| Benchmark on Mac ARM | Pending | Compare vs Apple libm (different algorithms than glibc) |\n| Benchmark on Windows MSVC | Pending | Compare vs MSVC CRT (different algorithms than glibc) |\n| Rewrite README | Done | Structured docs with SIMD benchmarks, accuracy tables |\n| Audit SIMD test edge cases | Done | NaN/inf/denorm coverage across all backends |\n| Update sin_pi_4 via Sollya fpminimax | Done | 3.3x better sup-norm error (2.44e-10 → 7.32e-11) |\n| Remove sin_wide/cos_wide | Done | Marginal 30% SIMD gain not worth maintaining; cos_wide unviable |\n| Consolidate eval tools | Done | Single `ulp_eval` tool with dispenso::parallel_for, covers 12 functions |\n| CMake build support | Done | Gated behind `-DDISPENSO_BUILD_FAST_MATH=ON` (experimental) |\n| Evaluate additional transcendentals | Pending | sinh, cosh, tanh, pow, hypot, expm1, log1p (see Post-V1 section) |\n\n---\n\n## Post-V1: Additional Functions\n\nPrioritized by demand in real-time graphics, physics, and ML inference workloads.\n\n### Priority 1 — Strong candidates\n\n| Function | Rationale |\n|----------|-----------|\n| `hypot(x, y)` | `sqrt(x*x + y*y)` with overflow/underflow protection. Very common in geometry code — dispenso's primary audience. Simple to implement well. |\n| `pow(x, y)` | General power function. `exp(y * log(x))` works as a stopgap but loses accuracy for integer exponents and has edge case issues (negative base, 0^0). Dedicated implementation can be faster and more correct. |\n| `sincos(x)` | Compute sin and cos simultaneously. Many workloads (rotation matrices, complex multiplication) need both. Shared range reduction makes this ~1.5x faster than separate sin+cos calls. |\n| `sinpi(x)`, `cospi(x)`, `sincospi(x)` | Compute sin(πx), cos(πx), or both. Exact at integer and half-integer arguments without range reduction error accumulation. Important for FFT twiddle factors, Chebyshev nodes, and anywhere the argument is naturally in units of π. |\n\n### Priority 2 — Useful in specific domains\n\n| Function | Rationale |\n|----------|-----------|\n| `expm1(x)` | `exp(x) - 1` with precision near zero. Important for numerical stability in financial, scientific, and signal processing code. |\n| `log1p(x)` | `log(1 + x)` with precision near zero. Paired with expm1 for stable computation. |\n| `tanh(x)` | ML activation function. Most ML runs on GPU, but CPU inference (edge devices, ONNX Runtime) would benefit. Can be derived from exp. |\n\n### Priority 3 — Niche / low demand\n\n| Function | Rationale |\n|----------|-----------|\n| `sinh(x)`, `cosh(x)` | Hyperbolic functions. Rare in hot loops outside of specialized physics simulations. Derivable from exp. |\n| `erf(x)`, `erfc(x)` | Error function. Statistical/ML use cases. GELU activation uses erf, but typically GPU-side. |\n| `pow(x, int n)` | Integer power specialization. Faster than general pow via repeated squaring. |\n| `fmod(x, y)`, `remainder(x, y)` | Modular arithmetic. Less clear speedup opportunity vs libc — these are integer-like. |\n| `lgamma(x)`, `tgamma(x)` | Gamma functions. Very niche. |\n\n### Future: GPU Device Functions (CUDA / HIP)\n\nThe tableless double-precision pow core (`pow_double_poly_core`) and its building\nblocks (`DoubleVec`, `exp2_split`, `logarithmSep`) are pure arithmetic with no\nplatform-specific intrinsics — they use only `+`, `-`, `*`, `fma`, and\nwidening/narrowing conversions. This makes them natural candidates for GPU device\nfunctions (`__device__`).\n\n**Motivation**: GPU shader math libraries (CUDA `__powf`, HIP `__ocml_pow_f32`)\ntrade accuracy for speed. A <1 ULP pow on-device would serve:\n- Physically-based rendering (PBR) and tone mapping\n- ML inference with numerical sensitivity (small-exponent power laws)\n- Scientific computing where double is too slow but single needs accuracy\n\n**Approach — double-float (df64)**: Consumer GPUs have 1/32 double-precision\nthroughput (only datacenter GPUs like A100/H100 have 1/2). A true `double`\ndetour would be a net loss on most hardware. Instead, use **double-float**\narithmetic: carry extended precision as a `(hi, lo)` pair of `float` values,\nusing single-precision FMA for error-free transforms. This runs at full `float`\nthroughput on all GPUs.\n\nThe existing `log2_ext` in `fast_math_impl.h` is essentially a double-float\nalgorithm (extended-precision log2 with FMA error tracking), but it was designed\nfor CPU SIMD where the division and extra ops are tolerable. A GPU df64 version\nwould:\n- Use the same `logarithmSep` range reduction (pure float/uint32)\n- Evaluate `log2(m)` as a df64 polynomial (hi+lo pair, FMA error tracking)\n- Multiply by `y` in df64 (Dekker splitting or FMA-based TwoProduct)\n- Feed the result to `exp2` (existing float exp2 + EFT correction)\n\nThis avoids double entirely while achieving similar accuracy (~46 mantissa\nbits in the y*log2(x) product). The CPU `DoubleVec` approach is the right\nreference for algorithm structure, but the GPU implementation would substitute\ndf64 pairs for actual doubles.\n\n**Key considerations**:\n- `__fma_rn` (round-to-nearest FMA) is available on all CUDA architectures\n  (sm_20+). HIP has `__fma`. Critical for df64 error-free transforms.\n- Float↔double conversions are free on datacenter GPUs; on consumer GPUs the\n  double path is prohibitive — df64 sidesteps this entirely.\n- The `pow_double_hybrid_core` table-based path could also work on GPU\n  (L1/shared memory lookups are fast), adapting gathers to `__ldg` or shared\n  memory preload. Worth benchmarking against pure-polynomial df64.\n- On datacenter GPUs with fast double (A100: 1/2 rate, H100: 1/2 rate), the\n  existing `DoubleVec<float>` scalar-double approach may win outright — worth\n  benchmarking both paths and dispatching based on `__CUDA_ARCH__`.\n\n### Not planned\n\n| Function | Reason |\n|----------|--------|\n| Double precision (`double`) variants | fast_math targets `float` workloads (graphics, real-time). Double-precision demand is low for our audience. Could be added later if justified. |\n| Complex math | Out of scope — different domain. |\n\n---\n\n## Post-V1: Infrastructure\n\n| Task | Priority | Notes |\n|------|----------|-------|\n| Benchmark automation script | High | Run all benchmarks, collect results, generate markdown tables. Per SLEEF: document CPU model, clock speed (turbo off), compiler version, OS. |\n| Accuracy measurement automation | High | Sweep full domain of each function, compute max ULP error vs MPFR (like SLEEF does). Currently ULP numbers are manually measured. |\n| Compiler Explorer (Godbolt) examples | Medium | Show generated assembly for scalar vs SIMD to demonstrate vectorization. |\n| Comparison benchmarks vs other libs | Medium | Benchmark against SLEEF, Eve (Expressive Vector Engine), and Highway contrib/math. Compare speed and accuracy on identical hardware/inputs. Useful for positioning and identifying where we can improve. |\n| Comparison table vs SLEEF/SVML | Medium | Side-by-side accuracy and speed comparison. Helps users decide. |\n| Refit asin polynomials via Sollya with explicit FMA | Medium | `asin_0_pt5` uses non-FMA polynomial (`a * b + c`), which the compiler may auto-contract differently on SIMD vs scalar, causing 1 ULP divergence. Refit coefficients via Sollya `fpminimax` targeting explicit FMA evaluation (like `sin_pi_4` was done). This will make scalar and SIMD paths produce identical results. |\n| Investigate Estrin polynomial evaluation | Medium | Current polynomials use Horner evaluation (sequential FMA chain). Estrin's scheme reduces critical-path depth from ~9 to ~4 FMAs, potentially improving SIMD throughput. However, coefficients were fitted for Horner evaluation order — switching to Estrin with existing coefficients regresses atan ULP from 3 to 4. Need to refit coefficients via Remez (requires modifying the boost-based Remez harness to use Estrin evaluation during fitting). Candidates: atan_poly, asin polynomials, and any other deep Horner chains. Also consider converting atan_poly to odd-only form (evaluate in x^2) to halve polynomial degree. |\n| CMake SIMD backend options | Medium | Add CMake options to enable specific SIMD backends (SSE4.1, AVX2, AVX-512, NEON, Highway) and set appropriate compiler flags (e.g. `-mavx2`, `-mavx512f`). Include option for `-march=native`. Also handle finding/fetching Highway when the Highway backend is enabled. |\n| Binary float constant representations | Medium | Replace decimal float literals with C99 hex float constants (e.g. `0x1.921fb6p+1f`) where appropriate. Hex floats are exact, avoid questions about truncation from excess decimal digits, and match the format used by Sollya/MPFR output. |\n| Doxygen documentation for public API | Medium | Add doxygen comments to all public functions documenting precision, domain, AccuracyTraits behavior, and SIMD compatibility. Note which functions ignore AccuracyTraits. |\n| `DefaultSimdFloat` usage examples | Medium | Show how to write portable SIMD code using the type alias. |\n| Power accounting hooks | Low | Original design goal — compile-time zero-overhead instrumentation for power profiling. Deferred. |\n\n---\n\n## Design Notes\n\n### Why not just use SLEEF?\n\ndispenso::fast_math occupies a different niche:\n\n1. **Tighter integration with dispenso** — Same build system, same namespace, same coding conventions. No external dependency to manage.\n2. **FloatTraits abstraction** — Generic programming over any SIMD type (including raw intrinsics) via a single template parameter. SLEEF requires calling platform-specific function names.\n3. **AccuracyTraits** — Compile-time selection between speed and accuracy variants via template parameter, not function name suffixes.\n4. **Simpler subset** — 17 functions vs SLEEF's 70+. Less code to maintain, audit, and understand.\n5. **Scalar-first design** — Every function works on plain `float` with the same API. SIMD is opt-in, not required.\n\nFor users who need the full breadth of SLEEF's function coverage, SLEEF is the right choice. For users who want fast transcendentals integrated into a C++ parallel computing library with a clean generic API, dispenso::fast_math fills that gap.\n\n### SIMD Architecture Evolution\n\nThe current SIMD wrapper design (`FloatTraits<T>`, `SimdTypeFor<T>`) supports\nfixed-width architectures (SSE, AVX, AVX-512, NEON) with native wrappers and\nvariable-width via Highway. This section outlines the path toward broader\narchitecture support and integration with dispenso's parallel algorithms.\n\n#### Variable-Length Vector Architectures\n\n**ARM SVE/SVE2** (128-2048 bit) and **RISC-V Vector Extension (RVV)** use\nruntime-determined vector lengths. Key differences from fixed-width SIMD:\n\n- Vector types are **sizeless** (`svfloat32_t`, `vfloat32m1_t`) — can't take\n  sizeof, store in arrays, or (portably) place in structs.\n- Comparisons return **predicate registers** (`svbool_t`, `vbool_t`), not\n  lane-wide float masks. This differs from SSE/AVX (float masks) and AVX-512\n  (bit masks), but the existing `BoolType_t<Flt>` / `bool_as_mask` abstraction\n  extends naturally to predicates.\n- RVV uses a **vector-length-agnostic (VLA)** programming model: `vsetvl(n)`\n  sets the number of elements to process per iteration, and the hardware\n  handles tail elements natively. This is closer to Cray-style vector\n  processing than traditional SIMD.\n- RVV's **LMUL** (register grouping) gangs 1-8 registers together, trading\n  register count for width. Effective width is `VLEN * LMUL / element_bits`,\n  all runtime-determined.\n\n**Short-term strategy**: Use Highway for SVE/RVV. Highway already dispatches\nto `HWY_SVE`, `HWY_SVE2`, and `HWY_RVV` targets. The `HwyFloat` wrapper\nworks regardless of underlying width. This avoids sizeless type complexity.\n\n**Medium-term strategy**: If SVE becomes a high-priority target (e.g. for\nNeoverse server workloads), add native `SveFloat` / `RvvFloat` wrappers with\npredicate-aware `FloatTraits`. The existing `BoolType` pattern extends cleanly.\n\n**POWER VMX/VSX**: Fixed 128-bit (4 lanes), similar to SSE. Low priority —\nniche HPC audience. Highway covers it via `HWY_PPC8` if needed.\n\n#### SimdOps: Cross-Lane Operations for Parallel Algorithms\n\n`FloatTraits<T>` provides per-element operations (arithmetic, comparisons,\nconditional blending) sufficient for fast_math. Dispenso's parallel algorithms\n(reductions, scans, partitions) additionally need **cross-lane** operations.\n\nProposed `SimdOps<T>` trait alongside `FloatTraits<T>`:\n\n```cpp\ntemplate <typename Flt>\nstruct SimdOps {\n  // Runtime vector width (compile-time for SSE/AVX, runtime for SVE/RVV).\n  static size_t width();\n\n  // Horizontal operations.\n  static float reduce_sum(Flt v);\n  static float reduce_min(Flt v);\n  static float reduce_max(Flt v);\n\n  // Prefix sums (within a single SIMD register).\n  static Flt inclusive_prefix_sum(Flt v);\n  static Flt exclusive_prefix_sum(Flt v);\n\n  // Lane permutations.\n  static Flt shuffle(Flt v, IntType_t<Flt> indices);\n  static Flt broadcast_lane(Flt v, int lane);\n  static Flt rotate(Flt v, int amount);\n};\n```\n\nThese are **building blocks** for dispenso's task-parallel algorithms, not\nfull algorithms. The SIMD block operations compose with dispenso's existing\ntask scheduler:\n\n1. **Phase 1** (parallel): Each task processes SIMD-width blocks using\n   `SimdOps` (e.g. block prefix sum + block total).\n2. **Phase 2** (sequential or recursive): Combine block totals across tasks.\n3. **Phase 3** (parallel): Each task applies its offset to its block results.\n\nThis decomposition keeps SIMD building blocks pure and stateless, while\ndispenso's `parallel_for` / `parallel_reduce` handles work distribution.\n\n#### Widening Operations\n\nMany reductions and scans require **widening accumulation** to avoid precision\nloss or overflow:\n\n- Sum of `float` buffer → `double` accumulator (catastrophic cancellation)\n- Prefix sum of `int16_t` → `int32_t` output (overflow prevention)\n- Histogram of `uint8_t` → `uint32_t` counts\n\nThis is a fundamental pattern, not a special case. The SIMD building blocks\nmust support it from the start:\n\n```cpp\ntemplate <typename Flt>\nstruct SimdOps {\n  using WideType = ...;  // SseFloat → SseDouble, NeonFloat → NeonDouble, etc.\n\n  // Widening convert: N narrow elements → N wide elements (2 output vectors).\n  static std::pair<WideType, WideType> widen(Flt v);\n\n  // Widening reduce: accumulate narrow elements in wide precision.\n  static scalar_t<WideType> reduce_sum_wide(Flt v);\n};\n```\n\nEvery architecture has native widening support: SSE `cvtps_pd`, NEON\n`vcvt_f64_f32`, SVE `svcvt_f64_f32_x`, RVV `vfwcvt`. RVV's LMUL system\nhandles widening especially naturally — `vfwcvt.f.f.v` converts N floats to\nN doubles using 2x the register group width with no loop splitting.\n"
  },
  {
    "path": "docs/design/parallel_algorithms.md",
    "content": "# Dispenso Parallel Algorithms Design Document\n\n## Overview\n\nThis document outlines the design for a set of parallel algorithms in dispenso that mirror\nthe C++ standard library algorithms but use dispenso's execution model. This provides users\nwith familiar interfaces while leveraging dispenso's thread pool control, work stealing,\nand nested parallelism support.\n\n## Motivation\n\nC++17 introduced execution policies for standard algorithms (`std::execution::par`), but:\n\n1. **No thread pool control** - Users cannot specify which thread pool to use or limit parallelism\n2. **Implementation-defined behavior** - Backends vary (TBB, OpenMP, proprietary)\n3. **Limited customization** - No options for chunking strategy, stealing multiplier, etc.\n4. **Nested parallelism issues** - Many implementations deadlock or perform poorly\n5. **C++17 requirement** - Not available to C++14 codebases\n\nDispenso parallel algorithms address these limitations while providing a familiar API.\n\n## Design Goals\n\n1. **API compatibility** - Mirror std algorithm signatures where practical\n2. **Performance** - Match or exceed std::execution::par performance\n3. **Composability** - Algorithms should work well together and support nesting\n4. **Flexibility** - Support custom thread pools and execution options\n5. **Incremental adoption** - Users can migrate algorithm-by-algorithm\n\n## Execution Policy\n\n### Core Types\n\n```cpp\nnamespace dispenso {\n\n/// Options controlling parallel execution\nstruct ParallelOptions {\n  /// Maximum threads to use (0 = use pool size)\n  uint32_t maxThreads = 0;\n\n  /// Minimum items per chunk to avoid excessive overhead\n  uint32_t minItemsPerChunk = 1;\n\n  /// Whether to wait for completion (always true for algorithms with return values)\n  bool wait = true;\n};\n\n/// Execution policy referencing a specific thread pool\nclass ParallelPolicy {\n public:\n  explicit ParallelPolicy(ThreadPool& pool, ParallelOptions options = {});\n  explicit ParallelPolicy(ParallelOptions options = {});  // Uses global pool\n\n  ThreadPool& pool() const;\n  const ParallelOptions& options() const;\n};\n\n/// Create a parallel execution policy using the global thread pool\ninline ParallelPolicy par(ParallelOptions options = {});\n\n/// Create a parallel execution policy using a specific thread pool\ninline ParallelPolicy par(ThreadPool& pool, ParallelOptions options = {});\n\n}  // namespace dispenso\n```\n\n### Usage Examples\n\n```cpp\n// Use global thread pool with defaults\nauto sum = dispenso::reduce(dispenso::par(), v.begin(), v.end(), 0);\n\n// Use custom thread pool\ndispenso::ThreadPool myPool(4);\ndispenso::for_each(dispenso::par(myPool), v.begin(), v.end(), process);\n\n// With options\ndispenso::sort(dispenso::par({.maxThreads = 2}), v.begin(), v.end());\n```\n\n## Algorithm Categories\n\nAlgorithms are grouped by implementation complexity and interdependencies.\n\n### Tier 1: Foundation Algorithms\n\nThese provide building blocks for other algorithms and should be implemented first.\n\n| Algorithm | Description | Building Block |\n|-----------|-------------|----------------|\n| `for_each` | Apply function to range | Uses `dispenso::for_each` directly |\n| `for_each_n` | Apply function to n elements | Uses `dispenso::for_each_n` directly |\n| `transform` | Transform range to output | Parallel iteration, no dependencies |\n| `fill` | Fill range with value | Parallel iteration, no dependencies |\n| `fill_n` | Fill n elements | Parallel iteration, no dependencies |\n\n### Tier 2: Reduction Algorithms\n\nThese require combining results from parallel work.\n\n| Algorithm | Description | Implementation Notes |\n|-----------|-------------|---------------------|\n| `reduce` | Reduce range with binary op | Per-thread accumulators + final reduction |\n| `transform_reduce` | Transform then reduce | Fused for efficiency |\n| `count` | Count elements matching value | Reduction with increment |\n| `count_if` | Count elements matching predicate | Reduction with conditional increment |\n\n### Tier 3: Search Algorithms\n\nThese may terminate early and require coordination.\n\n| Algorithm | Description | Implementation Notes |\n|-----------|-------------|---------------------|\n| `find` | Find first matching element | Parallel search with early termination |\n| `find_if` | Find first element matching predicate | Parallel search with early termination |\n| `find_if_not` | Find first element not matching | Parallel search with early termination |\n| `any_of` | Check if any element matches | Parallel search, return on first match |\n| `all_of` | Check if all elements match | Parallel search, return on first mismatch |\n| `none_of` | Check if no elements match | Parallel search, return on first match |\n\n### Tier 4: Mutating Algorithms\n\nThese modify the input range and may have ordering constraints.\n\n| Algorithm | Description | Implementation Notes |\n|-----------|-------------|---------------------|\n| `copy` | Copy range | Parallel iteration |\n| `copy_if` | Copy elements matching predicate | Parallel filter, requires output coordination |\n| `move` | Move range | Parallel iteration |\n| `replace` | Replace matching values | Parallel iteration |\n| `replace_if` | Replace values matching predicate | Parallel iteration |\n\n### Tier 5: Ordering Algorithms\n\nThese have complex parallelization patterns.\n\n| Algorithm | Description | Implementation Notes |\n|-----------|-------------|---------------------|\n| `sort` | Sort range | Parallel quicksort or mergesort |\n| `stable_sort` | Stable sort | Parallel mergesort |\n| `partial_sort` | Partial sort | Parallel selection + sort |\n| `nth_element` | Nth element partitioning | Parallel partitioning |\n| `unique` | Remove consecutive duplicates | Parallel compaction (complex) |\n\n### Tier 6: Numeric Algorithms\n\nFrom `<numeric>`, often used in scientific computing.\n\n| Algorithm | Description | Implementation Notes |\n|-----------|-------------|---------------------|\n| `inclusive_scan` | Inclusive prefix sum | Parallel scan algorithm |\n| `exclusive_scan` | Exclusive prefix sum | Parallel scan algorithm |\n| `transform_inclusive_scan` | Transform + inclusive scan | Fused operation |\n| `transform_exclusive_scan` | Transform + exclusive scan | Fused operation |\n\n## Implementation Strategy\n\n### When to Use Existing Dispenso Primitives\n\n**Use `dispenso::parallel_for` when:**\n- Work is embarrassingly parallel (no cross-iteration dependencies)\n- Output location is determined by input index\n- Examples: `transform`, `fill`, `replace`\n\n**Use `dispenso::for_each` when:**\n- Iterating over non-random-access containers\n- Work per element is the goal (side effects)\n- Examples: `for_each` (direct mapping)\n\n### When to Use Custom Implementation\n\n**Custom implementation needed when:**\n- Early termination is beneficial (`find`, `any_of`)\n- Results must be combined across threads (`reduce`, `count`)\n- Complex coordination required (`sort`, `unique`)\n- Memory access patterns benefit from custom chunking\n\n### Reduction Pattern\n\nFor algorithms that combine results (reduce, count, etc.):\n\n```cpp\ntemplate<typename Policy, typename It, typename T, typename BinaryOp>\nT reduce(Policy&& policy, It first, It last, T init, BinaryOp op) {\n  const auto n = std::distance(first, last);\n  if (n == 0) return init;\n\n  ThreadPool& pool = policy.pool();\n  const auto numThreads = std::min<size_t>(\n      pool.numThreads() + 1,  // +1 for calling thread\n      policy.options().maxThreads ? policy.options().maxThreads : pool.numThreads() + 1);\n\n  // Per-thread partial results\n  std::vector<T> partials;\n\n  dispenso::parallel_for(\n      partials,\n      [&init]() { return init; },  // Initialize each partial with identity\n      size_t{0}, static_cast<size_t>(n),\n      [&](T& partial, size_t start, size_t end) {\n        auto it = first;\n        std::advance(it, start);\n        for (size_t i = start; i < end; ++i, ++it) {\n          partial = op(partial, *it);\n        }\n      });\n\n  // Combine partials\n  T result = init;\n  for (const T& p : partials) {\n    result = op(result, p);\n  }\n  return result;\n}\n```\n\n### Early Termination Pattern\n\nFor search algorithms that can stop early:\n\n```cpp\ntemplate<typename Policy, typename It, typename Pred>\nIt find_if(Policy&& policy, It first, It last, Pred pred) {\n  const auto n = std::distance(first, last);\n  if (n == 0) return last;\n\n  std::atomic<ssize_t> foundIndex{-1};\n\n  dispenso::parallel_for(\n      policy.pool(),\n      size_t{0}, static_cast<size_t>(n),\n      [&](size_t i) {\n        // Skip if already found earlier\n        ssize_t found = foundIndex.load(std::memory_order_relaxed);\n        if (found >= 0 && static_cast<ssize_t>(i) > found) {\n          return;\n        }\n\n        auto it = first;\n        std::advance(it, i);\n        if (pred(*it)) {\n          // Atomically update to earliest found\n          ssize_t expected = foundIndex.load(std::memory_order_relaxed);\n          while ((expected < 0 || static_cast<ssize_t>(i) < expected) &&\n                 !foundIndex.compare_exchange_weak(expected, i)) {\n          }\n        }\n      });\n\n  ssize_t found = foundIndex.load();\n  if (found < 0) return last;\n\n  auto result = first;\n  std::advance(result, found);\n  return result;\n}\n```\n\nNote: The above is a simple implementation. A production version would use chunking\nfor better cache behavior and reduced atomic contention.\n\n## API Signatures\n\n### Compatibility with std\n\nWhere possible, signatures should match std exactly (minus the execution policy):\n\n```cpp\n// std signature:\ntemplate<class ExecutionPolicy, class ForwardIt, class T>\nT reduce(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, T init);\n\n// dispenso signature:\ntemplate<class ForwardIt, class T>\nT reduce(ParallelPolicy policy, ForwardIt first, ForwardIt last, T init);\n```\n\n### Signature Variations to Support\n\nFor each algorithm, support all standard overloads where practical:\n\n```cpp\n// reduce overloads\ntemplate<class It>\ntypename std::iterator_traits<It>::value_type\nreduce(ParallelPolicy policy, It first, It last);\n\ntemplate<class It, class T>\nT reduce(ParallelPolicy policy, It first, It last, T init);\n\ntemplate<class It, class T, class BinaryOp>\nT reduce(ParallelPolicy policy, It first, It last, T init, BinaryOp op);\n```\n\n### Deferred Signatures (TODO)\n\nSome overloads may be deferred if they add significant complexity:\n\n- Iterator sentinel overloads (C++20 ranges)\n- Projections (C++20)\n- Overloads requiring complex type deduction\n\n## Header Organization\n\n```\ndispenso/\n├── algorithm.h              // Main header, includes all algorithms\n├── algorithm/\n│   ├── for_each.h          // for_each, for_each_n\n│   ├── transform.h         // transform (unary and binary)\n│   ├── fill.h              // fill, fill_n\n│   ├── reduce.h            // reduce, transform_reduce\n│   ├── count.h             // count, count_if\n│   ├── find.h              // find, find_if, find_if_not\n│   ├── predicates.h        // any_of, all_of, none_of\n│   ├── copy.h              // copy, copy_if, copy_n\n│   ├── replace.h           // replace, replace_if\n│   ├── sort.h              // sort, stable_sort\n│   └── scan.h              // inclusive_scan, exclusive_scan\n└── execution_policy.h       // ParallelPolicy, ParallelOptions, par()\n```\n\n## Performance Considerations\n\n### Chunking Strategy\n\n- Default chunk size should amortize scheduling overhead\n- For small workloads, fall back to sequential execution\n- Allow user override via `ParallelOptions::minItemsPerChunk`\n\n### Memory Access Patterns\n\n- Prefer sequential memory access within chunks for cache efficiency\n- For random-access iterators, use index-based chunking\n- For forward iterators, pre-compute chunk boundaries\n\n### Avoiding False Sharing\n\n- Per-thread accumulators should be cache-line aligned\n- Use `dispenso::ConcurrentVector` for parallel output when needed\n\n### Nested Parallelism\n\n- Algorithms should work correctly when called from within parallel regions\n- Rely on dispenso's work-stealing to prevent deadlock\n\n### SIMD Optimization Opportunities\n\nFor certain algorithms with contiguous memory and simple element types, SIMD vectorization\ncan provide significant additional performance gains beyond thread-level parallelism:\n\n**High SIMD benefit:**\n- `fill`, `fill_n` - Vectorized stores\n- `copy`, `copy_n` - Vectorized loads/stores (or memcpy for trivially copyable types)\n- `transform` - When operation maps to SIMD intrinsics (e.g., arithmetic, min/max)\n- `reduce`, `transform_reduce` - Vectorized horizontal operations\n- `min_element`, `max_element`, `minmax_element` - SIMD comparisons\n- `count`, `count_if` - SIMD comparison + popcount\n- `equal`, `mismatch` - SIMD comparison\n- `find`, `find_if` - SIMD search with early termination\n\n**Implementation considerations:**\n- Require contiguous iterators (pointers or types satisfying contiguous_iterator)\n- Restrict to arithmetic types, pointers, or types with known SIMD-friendly operations\n- Consider platform-specific implementations (SSE, AVX, NEON) or rely on compiler auto-vectorization\n- May provide specializations for common cases (e.g., `float`, `double`, `int32_t`)\n- Chunk boundaries should be SIMD-aligned where beneficial\n\n## Testing Strategy\n\nEach algorithm should have tests for:\n\n1. **Correctness** - Compare results to sequential std:: version\n2. **Empty range** - Handle begin == end\n3. **Single element** - Degenerate case\n4. **Large range** - Verify parallelization occurs\n5. **Custom thread pool** - Non-global pool works correctly\n6. **Options** - maxThreads, minItemsPerChunk respected\n7. **Iterator types** - Random access, bidirectional, forward (where applicable)\n8. **Nested calls** - Algorithm called from within parallel_for\n\n## Implementation Phases\n\n### Phase 1: Foundation (Recommended First)\n\n1. `ParallelPolicy` and `par()` execution policy\n2. `for_each` / `for_each_n` (wraps existing dispenso::for_each)\n3. `transform` (unary version)\n4. `fill` / `fill_n`\n5. `reduce` (all overloads)\n6. `transform_reduce`\n\n### Phase 2: Search and Count\n\n1. `count` / `count_if`\n2. `find` / `find_if` / `find_if_not`\n3. `any_of` / `all_of` / `none_of`\n\n### Phase 3: Mutating\n\n1. `copy` / `copy_n`\n2. `copy_if`\n3. `replace` / `replace_if`\n4. `transform` (binary version)\n\n### Phase 4: Sorting\n\n1. `sort`\n2. `stable_sort`\n3. `partial_sort`\n4. `nth_element`\n\n## Sorting Implementation Details\n\nThis section provides detailed design for parallel sorting algorithms.\n\n### Shared Infrastructure\n\nAll sorting algorithms can share common building blocks:\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                      Public APIs                             │\n├─────────────────────┬─────────────────┬─────────────────────┤\n│ dispenso::sort      │ stable_sort     │ radix_sort          │\n│ (comparison-based)  │ (stable)        │ (integer keys)      │\n└──────────┬──────────┴────────┬────────┴──────────┬──────────┘\n           │                   │                   │\n           ▼                   ▼                   ▼\n┌─────────────────────────────────────────────────────────────┐\n│                   Shared Infrastructure                      │\n├─────────────────────────────────────────────────────────────┤\n│ • Sorting networks for small arrays (N ≤ 32)                │\n│ • Insertion sort fallback (N ≤ ~16-32)                      │\n│ • Parallel partitioning                                      │\n│ • Task spawning via TaskSet                                  │\n│ • Threshold tuning (serial vs parallel cutoff)              │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Sorting Networks\n\nFor small arrays (N ≤ 32), sorting networks provide optimal performance:\n\n- **Compile-time fixed structure** - No branches, predictable execution\n- **SIMD-friendly** - Can use min/max operations\n- **Near-optimal comparator count** - Dense coverage for N=2 to N=32\n- **Data-independent** - Same performance regardless of input order\n\n```cpp\nnamespace dispenso::detail {\n\n/// Conditionally swap two elements\ntemplate<typename T, typename Compare>\nDISPENSO_INLINE void compareSwap(T& a, T& b, Compare comp) {\n  // Branchless version for arithmetic types:\n  // auto should_swap = comp(b, a);\n  // auto tmp = should_swap ? a : b;  // min\n  // b = should_swap ? b : a;         // max\n  // a = tmp;\n\n  // Branch version (compiler may optimize):\n  if (comp(b, a)) {\n    using std::swap;\n    swap(a, b);\n  }\n}\n\n/// Sorting network for N=4 (5 comparators, depth 3)\ntemplate<typename T, typename Compare>\nvoid sortingNetwork4(T* arr, Compare comp) {\n  compareSwap(arr[0], arr[1], comp);\n  compareSwap(arr[2], arr[3], comp);\n  compareSwap(arr[0], arr[2], comp);\n  compareSwap(arr[1], arr[3], comp);\n  compareSwap(arr[1], arr[2], comp);\n}\n\n/// Near-optimal networks for all sizes 2-32\ntemplate<typename T, typename Compare>\nvoid sortingNetwork2(T* arr, Compare comp);\ntemplate<typename T, typename Compare>\nvoid sortingNetwork3(T* arr, Compare comp);\n// ... networks for 4-32\n\n/// Dispatch to appropriate sorting network\ntemplate<typename T, typename Compare>\nvoid smallSort(T* arr, size_t n, Compare comp) {\n  // Dispatch table or switch to networks for sizes 2-32\n  // All sizes covered by near-optimal networks\n  switch (n) {\n    case 0: case 1: return;\n    case 2: sortingNetwork2(arr, comp); return;\n    case 3: sortingNetwork3(arr, comp); return;\n    case 4: sortingNetwork4(arr, comp); return;\n    // ... etc through 32\n    default: assert(false && \"Use parallel sort for n > 32\");\n  }\n}\n\n/// For stable sort, insertion sort is better than trying to make networks stable\ntemplate<typename T, typename Compare>\nvoid stableSmallSort(T* arr, size_t n, Compare comp) {\n  // Insertion sort is naturally stable and simpler than adding\n  // index tracking to networks\n  for (size_t i = 1; i < n; ++i) {\n    T tmp = std::move(arr[i]);\n    size_t j = i;\n    while (j > 0 && comp(tmp, arr[j - 1])) {\n      arr[j] = std::move(arr[j - 1]);\n      --j;\n    }\n    arr[j] = std::move(tmp);\n  }\n}\n\n}  // namespace dispenso::detail\n```\n\n**Why networks for unstable, insertion sort for stable:**\n\n| Property | Sorting Networks | Insertion Sort |\n|----------|-----------------|----------------|\n| Stable | No (adding stability adds overhead) | Yes (naturally) |\n| Branchless | Yes | No |\n| SIMD-friendly | Yes | Limited |\n| Data-dependent perf | No (fixed comparisons) | Yes (O(n) best, O(n²) worst) |\n| Best for | Unstable small sort | Stable small sort |\n\n### dispenso::sort (Parallel Quicksort)\n\nPrimary comparison-based parallel sort.\n\n**Algorithm:**\n1. For small arrays (N ≤ threshold), use sorting network or insertion sort\n2. Choose pivot (median-of-3 or sampling for large arrays)\n3. Parallel partition around pivot\n4. Recursively sort partitions:\n   - Large partitions: spawn parallel tasks\n   - Small partitions: sort inline (serial)\n\n**Key parameters:**\n- `kSerialThreshold` - Below this, use serial sort (~10K-50K elements)\n- `kNetworkThreshold` - Below this, use sorting network (~32 elements)\n- `kSamplingThreshold` - Above this, use sampling for pivot selection\n\n```cpp\ntemplate<typename RandomIt, typename Compare>\nvoid sort(ParallelPolicy policy, RandomIt first, RandomIt last, Compare comp) {\n  const auto n = std::distance(first, last);\n  if (n <= kSerialThreshold) {\n    std::sort(first, last, comp);  // or custom serial sort\n    return;\n  }\n\n  TaskSet tasks(policy.pool());\n  parallelQuicksort(tasks, first, last, comp, /*depth=*/0);\n  tasks.wait();\n}\n\ntemplate<typename RandomIt, typename Compare>\nvoid parallelQuicksort(TaskSet& tasks, RandomIt first, RandomIt last,\n                       Compare comp, int depth) {\n  const auto n = std::distance(first, last);\n\n  // Base case: small arrays\n  if (n <= kNetworkThreshold) {\n    detail::smallSort(&*first, n, comp);\n    return;\n  }\n  if (n <= kSerialThreshold || depth > kMaxDepth) {\n    std::sort(first, last, comp);\n    return;\n  }\n\n  // Partition\n  auto pivot = selectPivot(first, last, comp);\n  auto mid = partition(first, last, pivot, comp);\n\n  // Recurse in parallel\n  tasks.schedule([&tasks, first, mid, comp, depth]() {\n    parallelQuicksort(tasks, first, mid, comp, depth + 1);\n  });\n  parallelQuicksort(tasks, mid, last, comp, depth + 1);\n}\n```\n\n### dispenso::stable_sort (Parallel Mergesort)\n\nStable comparison-based parallel sort using mergesort.\n\n**Algorithm:**\n1. Divide array into chunks\n2. Sort chunks in parallel (can use quicksort for chunks)\n3. Parallel merge sorted chunks\n\n**Note:** Requires O(n) auxiliary memory.\n\n### MSD Radix Sort (Hybrid)\n\nFor integer keys, MSD (Most Significant Digit) radix sort with hybrid fallback.\n\n**Algorithm:**\n1. Count elements per bucket based on current digit (parallel histogram)\n2. Compute prefix sums for bucket boundaries\n3. Distribute elements to buckets (parallel scatter)\n4. Recursively sort each bucket:\n   - Large buckets: parallel MSD radix on next digit\n   - Medium buckets: switch to comparison sort\n   - Small buckets: sorting network\n\n**Interface:**\n\n```cpp\nnamespace dispenso {\n\n/// Sort integers using parallel MSD radix sort\n/// Requires auxiliary memory of size n\ntemplate<typename RandomIt>\nvoid radix_sort(ParallelPolicy policy, RandomIt first, RandomIt last);\n\n/// Sort integers with custom key extraction\ntemplate<typename RandomIt, typename KeyFn>\nvoid radix_sort(ParallelPolicy policy, RandomIt first, RandomIt last, KeyFn key);\n\n/// Sort with pre-allocated auxiliary buffer\ntemplate<typename RandomIt, typename KeyFn>\nvoid radix_sort(ParallelPolicy policy, RandomIt first, RandomIt last,\n                KeyFn key, typename std::iterator_traits<RandomIt>::value_type* aux);\n\n}  // namespace dispenso\n```\n\n**Hybrid strategy:**\n- Start with 8-bit or 11-bit digits (256 or 2048 buckets)\n- Switch to comparison sort when bucket size < threshold (~256-1024)\n- Use sorting network for tiny buckets (< 32)\n\n**Performance characteristics:**\n- O(n * k) where k = number of digits\n- Excellent cache behavior with appropriate digit size\n- Outperforms comparison sort for large arrays of integers/floats\n\n### Performance Considerations\n\n**Threshold tuning:**\n- Thresholds are hardware-dependent (cache size, core count)\n- Consider auto-tuning or platform-specific defaults\n- Provide user override via ParallelOptions\n\n**Memory access:**\n- Partition in-place to minimize memory traffic\n- For stable_sort/radix_sort, pre-allocate auxiliary buffer\n- Consider NUMA awareness for very large arrays\n\n**Task granularity:**\n- Avoid spawning tasks for very small partitions\n- Limit recursion depth to prevent task explosion\n- Use work-stealing naturally via TaskSet\n\n### Phase 5: Advanced\n\n1. `inclusive_scan` / `exclusive_scan`\n2. `transform_inclusive_scan` / `transform_exclusive_scan`\n3. `unique`\n\n## Complete Algorithm Inventory\n\nThis section tracks all C++ standard library algorithms that support parallel execution policies.\nAlgorithms are categorized by priority based on their value in a parallel context.\n\n### Priority Definitions\n\n- **High**: Algorithms that benefit significantly from parallelization and are commonly used\n- **Medium**: Algorithms with moderate parallel benefit or less common use cases\n- **Low**: Algorithms where parallelization provides minimal benefit or adds unnecessary overhead\n\n### High Priority Algorithms\n\n| Algorithm | Status | Notes |\n|-----------|--------|-------|\n| `for_each` | Planned (Phase 1) | Core building block |\n| `for_each_n` | Planned (Phase 1) | Core building block |\n| `transform` | Planned (Phase 1) | Embarrassingly parallel |\n| `reduce` | Planned (Phase 1) | Common reduction pattern |\n| `transform_reduce` | Planned (Phase 1) | Fused transform + reduce |\n| `sort` | Planned (Phase 4) | High-value, well-understood parallel algorithms |\n| `stable_sort` | Planned (Phase 4) | Parallel mergesort |\n| `fill` | Planned (Phase 1) | Simple parallel write |\n| `fill_n` | Planned (Phase 1) | Simple parallel write |\n| `copy` | Planned (Phase 3) | Parallel memory copy |\n| `copy_n` | Planned (Phase 3) | Parallel memory copy |\n| `inclusive_scan` | Planned (Phase 5) | Prefix sum, scientific computing |\n| `exclusive_scan` | Planned (Phase 5) | Prefix sum, scientific computing |\n| `transform_exclusive_scan` | Planned (Phase 5) | Fused operation |\n| `transform_inclusive_scan` | Planned (Phase 5) | Fused operation |\n| `count` | Planned (Phase 2) | Parallel reduction |\n| `count_if` | Planned (Phase 2) | Parallel reduction with predicate |\n| `find` | Planned (Phase 2) | Parallel search with early termination |\n| `find_if` | Planned (Phase 2) | Parallel search with early termination |\n| `find_if_not` | Planned (Phase 2) | Parallel search with early termination |\n| `any_of` | Planned (Phase 2) | Parallel short-circuit evaluation |\n| `all_of` | Planned (Phase 2) | Parallel short-circuit evaluation |\n| `none_of` | Planned (Phase 2) | Parallel short-circuit evaluation |\n| `inner_product` | Not yet planned | Equivalent to transform_reduce |\n| `adjacent_difference` | Not yet planned | Parallel stencil operation |\n| `max_element` | Not yet planned | Parallel reduction to find max |\n| `min_element` | Not yet planned | Parallel reduction to find min |\n| `minmax_element` | Not yet planned | Parallel reduction to find both |\n\n### Medium Priority Algorithms\n\n| Algorithm | Status | Notes |\n|-----------|--------|-------|\n| `copy_if` | Planned (Phase 3) | Requires output coordination |\n| `replace` | Planned (Phase 3) | Simple parallel mutation |\n| `replace_if` | Planned (Phase 3) | Simple parallel mutation |\n| `replace_copy` | Not yet planned | Parallel copy with replacement |\n| `replace_copy_if` | Not yet planned | Parallel copy with conditional replacement |\n| `move` | Planned (Phase 3) | Parallel move semantics |\n| `partial_sort` | Planned (Phase 4) | Parallel selection + sort |\n| `partial_sort_copy` | Not yet planned | Parallel partial sort to output |\n| `nth_element` | Planned (Phase 4) | Parallel partitioning |\n| `partition` | Not yet planned | Parallel partitioning |\n| `stable_partition` | Not yet planned | Stable parallel partitioning |\n| `partition_copy` | Not yet planned | Parallel partition to two outputs |\n| `unique` | Planned (Phase 5) | Complex parallel compaction |\n| `unique_copy` | Not yet planned | Parallel unique to output |\n| `merge` | Not yet planned | Parallel merge of sorted ranges |\n| `inplace_merge` | Not yet planned | In-place parallel merge |\n| `set_union` | Not yet planned | Parallel set operation |\n| `set_intersection` | Not yet planned | Parallel set operation |\n| `set_difference` | Not yet planned | Parallel set operation |\n| `set_symmetric_difference` | Not yet planned | Parallel set operation |\n| `generate` | Not yet planned | Parallel generation (if generator is thread-safe) |\n| `generate_n` | Not yet planned | Parallel generation (if generator is thread-safe) |\n| `remove` | Not yet planned | Parallel compaction |\n| `remove_if` | Not yet planned | Parallel compaction with predicate |\n| `remove_copy` | Not yet planned | Parallel filtered copy |\n| `remove_copy_if` | Not yet planned | Parallel filtered copy with predicate |\n| `reverse` | Not yet planned | Parallel in-place reversal |\n| `reverse_copy` | Not yet planned | Parallel reverse to output |\n| `rotate` | Not yet planned | Parallel rotation |\n| `rotate_copy` | Not yet planned | Parallel rotate to output |\n| `swap_ranges` | Not yet planned | Parallel swap |\n| `uninitialized_copy` | Not yet planned | Parallel uninitialized memory copy |\n| `uninitialized_copy_n` | Not yet planned | Parallel uninitialized memory copy |\n| `uninitialized_fill` | Not yet planned | Parallel uninitialized fill |\n| `uninitialized_fill_n` | Not yet planned | Parallel uninitialized fill |\n| `equal` | Not yet planned | Parallel comparison with early termination |\n| `mismatch` | Not yet planned | Parallel search for first difference |\n| `is_sorted` | Not yet planned | Parallel scan; less common with large sequences |\n| `is_sorted_until` | Not yet planned | Parallel scan; less common with large sequences |\n| `is_partitioned` | Not yet planned | Parallel scan; less common with large sequences |\n| `lexicographical_compare` | Not yet planned | Parallel comparison; less common with large sequences |\n| `includes` | Not yet planned | Parallel subset check |\n| `search` | Not yet planned | Parallel subsequence search |\n| `search_n` | Not yet planned | Parallel consecutive value search |\n\n### Low Priority Algorithms\n\nThese algorithms have limited benefit from parallelization due to their nature\n(e.g., heap operations have inherent sequential dependencies, or the operations\nare too simple to justify parallel overhead in most cases).\n\n| Algorithm | Status | Notes |\n|-----------|--------|-------|\n| `is_heap` | Not yet planned | Heap structure has sequential dependencies |\n| `is_heap_until` | Not yet planned | Heap structure has sequential dependencies |\n| `adjacent_find` | Not yet planned | Requires checking adjacent pairs, limited benefit |\n| `find_end` | Not yet planned | Searching from end, complex parallelization |\n| `find_first_of` | Not yet planned | Multi-target search, moderate complexity |\n\n### Algorithm Status Legend\n\n- **Planned (Phase N)**: Included in implementation roadmap\n- **Not yet planned**: Identified but not scheduled; may be added based on demand\n- **Implemented**: Available in dispenso (update when completed)\n- **Deferred**: Explicitly deferred due to complexity or low value\n\n## Open Questions\n\n1. **Namespace**: Should algorithms live in `dispenso::` or a sub-namespace like `dispenso::alg::`?\n\n2. **Sequential fallback**: Should there be automatic fallback to sequential for small inputs?\n   Recommended: Yes, with a reasonable threshold (e.g., < 1000 elements or < numThreads chunks).\n\n3. **Exception handling**: How should exceptions from user functors be handled?\n   Recommended: Follow std behavior - propagate one exception, others may be lost.\n\n4. **Allocator support**: Should algorithms that need temporary storage accept allocators?\n   Recommended: Defer to later; use dispenso's internal allocation initially.\n\n## References\n\n- [C++ Standard Algorithms Library](https://en.cppreference.com/w/cpp/algorithm)\n- [C++17 Execution Policies](https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag)\n- [P0024R2 - The Parallelism TS Should be Standardized](https://wg21.link/p0024r2)\n\n## Implementation Checklist\n\nAlgorithms in implementation order. Check off as completed.\n\n### Phase 1: Foundation\n- [ ] `for_each`\n- [ ] `for_each_n`\n- [ ] `transform`\n- [ ] `fill`\n- [ ] `fill_n`\n- [ ] `reduce`\n- [ ] `transform_reduce`\n\n### Phase 2: Search and Count\n- [ ] `count`\n- [ ] `count_if`\n- [ ] `find`\n- [ ] `find_if`\n- [ ] `find_if_not`\n- [ ] `any_of`\n- [ ] `all_of`\n- [ ] `none_of`\n\n### Phase 3: Mutating\n- [ ] `copy`\n- [ ] `copy_n`\n- [ ] `copy_if`\n- [ ] `move`\n- [ ] `replace`\n- [ ] `replace_if`\n\n### Phase 4: Sorting\n- [ ] `sort`\n- [ ] `stable_sort`\n- [ ] `partial_sort`\n- [ ] `nth_element`\n\n### Phase 5: Advanced\n- [ ] `inclusive_scan`\n- [ ] `exclusive_scan`\n- [ ] `transform_inclusive_scan`\n- [ ] `transform_exclusive_scan`\n- [ ] `unique`\n\n### Future (High Priority)\n- [ ] `min_element`\n- [ ] `max_element`\n- [ ] `minmax_element`\n- [ ] `inner_product`\n- [ ] `adjacent_difference`\n\n### Future (Medium Priority)\n- [ ] `replace_copy`\n- [ ] `replace_copy_if`\n- [ ] `partial_sort_copy`\n- [ ] `partition`\n- [ ] `stable_partition`\n- [ ] `partition_copy`\n- [ ] `unique_copy`\n- [ ] `merge`\n- [ ] `inplace_merge`\n- [ ] `set_union`\n- [ ] `set_intersection`\n- [ ] `set_difference`\n- [ ] `set_symmetric_difference`\n- [ ] `generate`\n- [ ] `generate_n`\n- [ ] `remove`\n- [ ] `remove_if`\n- [ ] `remove_copy`\n- [ ] `remove_copy_if`\n- [ ] `reverse`\n- [ ] `reverse_copy`\n- [ ] `rotate`\n- [ ] `rotate_copy`\n- [ ] `swap_ranges`\n- [ ] `uninitialized_copy`\n- [ ] `uninitialized_copy_n`\n- [ ] `uninitialized_fill`\n- [ ] `uninitialized_fill_n`\n- [ ] `equal`\n- [ ] `mismatch`\n- [ ] `is_sorted`\n- [ ] `is_sorted_until`\n- [ ] `is_partitioned`\n- [ ] `lexicographical_compare`\n- [ ] `includes`\n- [ ] `search`\n- [ ] `search_n`\n\n### Future (Low Priority)\n- [ ] `is_heap`\n- [ ] `is_heap_until`\n- [ ] `adjacent_find`\n- [ ] `find_end`\n- [ ] `find_first_of`\n"
  },
  {
    "path": "docs/design/release_checklist.md",
    "content": "# Release Checklist\n\nPost-release tasks and reminders for package manager updates.\n\n## vcpkg: Remove temporary patches\n\nThe v1.5.0 vcpkg port (`microsoft/vcpkg` PR #49633) includes two workarounds\nfor upstream bugs. Remove them once the release includes the fixes:\n\n1. **`fix-arm64-platform-define.patch`** — `notifier_common.h` defined `_ARM_`\n   instead of `_ARM64_` on ARM64 Windows, causing `winnt.h` compilation\n   failures. Fixed on `main`. Remove the patch file and the `PATCHES` block\n   from `portfile.cmake`.\n\n2. **`-DDISPENSO_SHARED_LIB=${DISPENSO_SHARED}`** — dispenso's\n   `DISPENSO_SHARED_LIB` option ignored `BUILD_SHARED_LIBS`, producing DLLs in\n   static triplets. Fixed on `main` (defaults to `BUILD_SHARED_LIBS` when set).\n   Remove the `string(COMPARE EQUAL ...)` line and the `-DDISPENSO_SHARED_LIB`\n   option from `portfile.cmake`.\n"
  },
  {
    "path": "docs/design/roadmap.md",
    "content": "# Dispenso Roadmap\n\nThis document tracks planned features and improvements for the dispenso library.\n\n## In Progress\n\n| Feature | Status | Notes |\n|---------|--------|-------|\n| vcpkg package | In progress | External PR to microsoft/vcpkg |\n| Conan package | In progress | External PR to conan-center-index |\n| ConcurrentHashMap | In progress | High-value concurrent container |\n\n## Planned\n\n### High Priority\n\n| Feature | Description | Doc |\n|---------|-------------|-----|\n| Parallel sorting | `dispenso::sort` and MSD radix hybrid | [parallel_algorithms.md](parallel_algorithms.md) |\n| Parallel algorithms (Phase 1) | for_each, transform, fill, reduce | [parallel_algorithms.md](parallel_algorithms.md) |\n| C++20 concepts | Better error messages with concept constraints | [cpp20_concepts.md](cpp20_concepts.md) |\n| Benchmark automation | Script to run benchmarks and generate charts | See benchmarks/ |\n| Compiler Explorer examples | Godbolt links in README for try-it-now experience | - |\n\n### Medium Priority\n\n| Feature | Description | Doc |\n|---------|-------------|-----|\n| Scalable allocator | Thread-caching allocator to eliminate malloc contention in concurrent growth (ConcurrentVector `parallel` is 3-5x faster with tcmalloc/jemalloc vs glibc) | - |\n| Parallel algorithms (Phase 2-3) | Search, count, copy, replace | [parallel_algorithms.md](parallel_algorithms.md) |\n| Barrier/Semaphore | C++20-style synchronization for C++14/17 | - |\n| ConcurrentQueue | Public API for blocking MPMC queue | - |\n\n### Lower Priority\n\n| Feature | Description | Doc |\n|---------|-------------|-----|\n| Parallel algorithms (Phase 4-5) | Sorting, scan, unique | [parallel_algorithms.md](parallel_algorithms.md) |\n| Coroutine integration | Coroutine-based task scheduling | [coroutines.md](coroutines.md) |\n| Single-header amalgamation | Full library in one header | - |\n\n## ConcurrentVector Optimization Notes\n\n### Optimizations Applied (Default Traits)\n\nThree categories of optimization have been applied to ConcurrentVector:\n\n1. **Inline asm `bsr` for `detail::log2`** on x86 GCC/Clang, plus 32-bit\n   overloads and `unsigned long` disambiguation for macOS. Prevents Clang from\n   decomposing `63 - __builtin_clzll` back into `bsrq + xorq` when inlined\n   into arithmetic.\n\n2. **Platform-adaptive `bucketAndSubIndexForIndex`**: branching fast path\n   (early return for `index < firstBucketLen_`) on MSVC and ARM where branch\n   predictors handle the sequential pattern well; branchless cmov path on\n   Clang/GCC x86 where cmovs avoid misprediction penalties.\n\n3. **Non-atomic buffer pointer cache (`cachedPtrs_[]`)** on non-ARM platforms.\n   Packs 8 pointers per cache line (vs 1 per line for `AlignedAtomic\n   buffers_[]`), dramatically improving `operator[]` and iterator read paths.\n   Disabled on ARM where cache-line invalidation on every write exceeds the\n   read benefit. Cache stores are ordered before the release store to\n   `buffers_[]`, so any acquire on `buffers_[]` guarantees cache visibility.\n\n### Impact on Alternative Traits\n\n| Trait | Values | Optimization Interaction |\n|-------|--------|--------------------------|\n| `kPreferBuffersInline` | `false` | Cache is *more* valuable — bypasses the extra indirection through heap-allocated `buffers_[]` pointer |\n| `kIteratorPreferSpeed` | `false` (compact iterator) | Benefits *disproportionately* — compact iterator calls `operator[]` (and thus `cachedBuffer` + `bucketAndSubIndexForIndex`) on every dereference, vs speed iterator which only calls on bucket transitions |\n| `kReallocStrategy` | `kHalfBufferAhead`, `kFullBufferAhead` | No interaction — earlier allocation just means cache is populated earlier |\n\n**Conclusion:** All optimizations apply uniformly across trait combinations.\nThe current defaults (`kPreferBuffersInline=true`, `kIteratorPreferSpeed=true`,\n`kReallocStrategy=kAsNeeded`) remain the best general-purpose configuration.\nThe compact iterator (`kIteratorPreferSpeed=false`) benefits the most from the\n`cachedPtrs_` and `log2` optimizations in relative terms, since it hits the\nindexed access path on every element access.\n\n### Future Work\n\n- **Server ARM (Graviton) benchmarking**: The `DISPENSO_HAS_CACHED_PTRS`\n  guard currently disables the cache on all ARM (`__aarch64__`). If server ARM\n  shows different cache pressure characteristics than mobile ARM, a more\n  targeted guard could re-enable it selectively.\n- **Scalable allocator** (see Medium Priority above): Concurrent growth\n  benchmarks show 3-5x improvement with tcmalloc/jemalloc vs glibc malloc,\n  suggesting a thread-caching allocator would benefit all trait combinations.\n\n## Completed\n\n| Feature | Version | Notes |\n|---------|---------|-------|\n| `dispenso.h` convenience header | 1.5.0 | Includes all public headers |\n| `util.h` public utilities | 1.5.0 | Exposes internal utilities |\n| OpenMP migration guide | 1.4.x | docs/migrating_from_openmp.md |\n| TBB migration guide | 1.4.x | docs/migrating_from_tbb.md |\n| awesome-cpp listing | - | Listed in fffaraz/awesome-cpp |\n| awesome-modern-cpp listing | - | Listed in rigtorp/awesome-modern-cpp |\n\n## External Submissions\n\n| Target | Status | Notes |\n|--------|--------|-------|\n| awesome-cpp | Listed | fffaraz/awesome-cpp |\n| awesome-modern-cpp | Listed | rigtorp/awesome-modern-cpp |\n| awesome-high-performance-computing | Listed | Already present in dstansby/awesome-high-performance-computing |\n| awesome-scientific-computing | Not applicable | Focus is numerical methods, not parallelism libraries |\n| awesome-hpc | Not applicable | Focus is cluster infrastructure, not app-level parallelism |\n| vcpkg | In progress | - |\n| Conan | In progress | - |\n\n## Subcomponent Roadmaps\n\n| Component | Doc |\n|-----------|-----|\n| dispenso::fast_math | [fast_math_roadmap.md](fast_math_roadmap.md) |\n\n## Ideas / Backlog\n\nThese are ideas that may be pursued based on community feedback:\n\n- CUDA graph mappings (TaskFlow has this; worth exploring for dispenso's Graph)\n- Lock-free stack\n- Range-based API wrappers (explicit opt-in)\n- SIMD-optimized algorithms\n- Integration examples (game engines, scientific computing)\n- Discord/Slack community channel\n- Windows thread pool wake strategy tuning:\n  - Current approach uses unconditional `WakeByAddressAll` in `wakeN()`. The primary benefit is **parallel wake-up**: all threads begin their OS-level wake simultaneously, rather than serially. Thread wake-up latency (scheduler, context switch, cache warm-up) dominates — the `WakeByAddress` syscall itself is fast (<1 us)\n  - Secondary benefit: the scheduling thread makes one syscall instead of N, freeing it to enqueue work or start its own computation sooner. This matters because the scheduling thread cannot worksteal until the queue is saturated, so every microsecond spent in wake syscalls is a microsecond of dead time where neither the caller nor the (still-sleeping) pool threads are making progress\n  - The increased spin constants (kBackoffYield=100, kBackoffSleep=120 vs Linux's 50/55) are complementary: keeping threads in spin phase longer avoids the expensive wake-up latency entirely. Sub-microsecond spin cost vs 10s-of-microsecond wake-up cost\n  - Benchmarks showed WakeAll outperforms the macOS-style heuristic (`n >= sleeping/2` → wakeAll, else wake individually), but thresholds N/2, N/3, N/4 were tested — not smaller fractions like N/16 that might limit thundering herd while still avoiding serial wake overhead\n  - The spin constant and WakeAll changes were not benchmarked independently\n  - Investigate: (1) whether a lower threshold (e.g., `n < sleeping/16`) balances thundering herd vs parallel wake benefit, (2) whether the spin constants should be tuned independently, (3) steady-state single-task patterns where WakeAll wakes unnecessary threads\n  - Requires Windows benchmarking access to validate\n- NUMA and topology awareness (phased):\n  - Windows processor group support for >64 threads (less critical as newer Windows versions handle this automatically)\n  - Topology query API: expose NUMA node count, core-to-node mapping, and inter-node distances (Linux: `/sys/devices/system/node/` or `libnuma`; Windows: `GetLogicalProcessorInformationEx`)\n  - Per-NUMA-node thread pools: opt-in pool construction affinitized to a specific node, composable with existing TaskSet/Future APIs\n  - NUMA-aware allocator: STL-compatible allocator for node-local allocation (`mbind`/`numa_alloc_onnode` on Linux, `VirtualAllocExNuma` on Windows), paired with first-touch initialization guidance\n"
  },
  {
    "path": "docs/getting_started.md",
    "content": "# Getting Started {#getting_started}\n\nThis guide walks through the core features of dispenso with working examples.\nEach section includes a complete, compilable example that you can build and run.\n\n## Installation\n\nSee the [README](https://github.com/facebookincubator/dispenso) for installation\ninstructions. Dispenso requires C++14 and CMake 3.12+.\n\nTo build the examples:\n\n```bash\nmkdir build && cd build\ncmake .. -DDISPENSO_BUILD_EXAMPLES=ON\nmake\n```\n\n## Basic Concepts\n\n### Thread Pools\n\nAt the heart of dispenso is the `ThreadPool`. A thread pool manages a set of\nworker threads that execute tasks. You can use the global thread pool or create\nyour own:\n\n```cpp\n#include <dispenso/thread_pool.h>\n\n// Use the global thread pool (recommended for most cases)\ndispenso::ThreadPool& pool = dispenso::globalThreadPool();\n\n// Or create a custom pool with a specific number of threads\ndispenso::ThreadPool myPool(4);  // 4 worker threads\n```\n\n> **Note:** `globalThreadPool()` defaults to `std::thread::hardware_concurrency() - 1`\n> worker threads, since the calling thread typically participates in computation.\n> Use `dispenso::resizeGlobalThreadPool(n)` to change it.\n\n### Task Sets\n\nA `TaskSet` groups related tasks and provides a way to wait for their completion:\n\n```cpp\n#include <dispenso/task_set.h>\n\ndispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\ntaskSet.schedule([]() { /* task 1 */ });\ntaskSet.schedule([]() { /* task 2 */ });\n\ntaskSet.wait();  // Block until all tasks complete\n```\n\n---\n\n## Your First Parallel Loop\n\nThe simplest way to parallelize work is with `parallel_for`. It distributes\nloop iterations across available threads.\n\n<!-- @example parallel_for_example.cpp -->\n\n**Simple per-element parallel loop:**\n\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Process each element independently in parallel\ndispenso::parallel_for(0, kArraySize, [&](size_t i) { output[i] = std::sqrt(input[i]); });\n```\n\n**Reduction with per-thread state:**\n\n```cpp\nstd::vector<double> partialSums;\ndispenso::parallel_for(\n    partialSums,\n    []() { return 0.0; }, // State initializer\n    size_t{0},\n    kArraySize,\n    [&](double& localSum, size_t start, size_t end) {\n      for (size_t i = start; i < end; ++i) {\n        localSum += input[i];\n      }\n    });\n\n// Combine partial sums\ndouble totalSum = 0.0;\nfor (double partial : partialSums) {\n  totalSum += partial;\n}\n```\n\nSee [full example](../examples/parallel_for_example.cpp).\n\nKey points:\n- Use the simple form for independent per-element work\n- Use chunked ranges when you want to control work distribution\n- Per-thread state enables efficient reductions\n- Options let you control parallelism and chunking strategy\n\n---\n\n## Parallel Iteration with for_each\n\nWhen you have a container rather than an index range, use `for_each`:\n\n<!-- @example for_each_example.cpp -->\n\n**Parallel for_each on a vector:**\n\n```cpp\n#include <dispenso/for_each.h>\n\nstd::vector<double> values = {1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0};\n\n// Apply square root to each element in parallel\ndispenso::for_each(values.begin(), values.end(), [](double& val) { val = std::sqrt(val); });\n```\n\n**for_each_n with explicit count:**\n\n```cpp\nstd::vector<int> partial = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};\n\n// Only process first 5 elements\ndispenso::for_each_n(partial.begin(), 5, [](int& n) { n += 100; });\n```\n\nSee [full example](../examples/for_each_example.cpp).\n\nKey points:\n- Works with any iterator type (including non-random-access iterators)\n- `for_each_n` takes an explicit count\n- Pass a `TaskSet` for external synchronization control\n\n---\n\n## Working with Tasks\n\nFor more complex task patterns, use `TaskSet` and `ConcurrentTaskSet` directly:\n\n<!-- @example task_set_example.cpp -->\n\n**Basic TaskSet:**\n\n```cpp\n#include <dispenso/task_set.h>\n\ndispenso::TaskSet taskSet(dispenso::globalThreadPool());\nstd::atomic<int> counter(0);\n\nfor (int i = 0; i < 10; ++i) {\n  taskSet.schedule([&counter, i]() { counter.fetch_add(i, std::memory_order_relaxed); });\n}\n\ntaskSet.wait();\n```\n\n**ConcurrentTaskSet with nested scheduling:**\n\n```cpp\ndispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\nstd::atomic<int> total(0);\n\nfor (int i = 0; i < 5; ++i) {\n  taskSet.schedule([&taskSet, &total, i]() {\n    // Each task schedules two sub-tasks\n    for (int j = 0; j < 2; ++j) {\n      taskSet.schedule(\n          [&total, i, j]() { total.fetch_add(i * 10 + j, std::memory_order_relaxed); });\n    }\n  });\n}\n\ntaskSet.wait();\n```\n\nSee [full example](../examples/task_set_example.cpp).\n\nKey points:\n- `TaskSet` is for single-threaded scheduling\n- `ConcurrentTaskSet` allows scheduling from multiple threads\n- Both support cancellation for cooperative early termination\n- The destructor waits for all tasks to complete\n\n---\n\n## Futures for Async Results\n\nWhen you need return values from async operations, use `Future`:\n\n<!-- @example future_example.cpp -->\n\n**Basic async and get:**\n\n```cpp\n#include <dispenso/future.h>\n\ndispenso::Future<int> future = dispenso::async([]() {\n  int result = 0;\n  for (int i = 1; i <= 100; ++i) {\n    result += i;\n  }\n  return result;\n});\n\nint result = future.get();  // blocks until ready\n```\n\n**Chaining with then():**\n\n```cpp\ndispenso::Future<double> chainedFuture = dispenso::async([]() {\n                                           return 16.0;\n                                         })\n                                             .then([](dispenso::Future<double>&& prev) {\n                                               return std::sqrt(prev.get());\n                                             })\n                                             .then([](dispenso::Future<double>&& prev) {\n                                               return prev.get() * 2.0;\n                                             });\n```\n\n**when_all for multiple futures:**\n\n```cpp\ndispenso::Future<int> f1 = dispenso::async([]() { return 10; });\ndispenso::Future<int> f2 = dispenso::async([]() { return 20; });\ndispenso::Future<int> f3 = dispenso::async([]() { return 30; });\n\nauto allFutures = dispenso::when_all(std::move(f1), std::move(f2), std::move(f3));\nauto tuple = allFutures.get();\nint sum = std::get<0>(tuple).get() + std::get<1>(tuple).get() + std::get<2>(tuple).get();\n```\n\nSee [full example](../examples/future_example.cpp).\n\nKey points:\n- `async()` launches work and returns a `Future`\n- `then()` chains dependent computations\n- `when_all()` waits for multiple futures\n- `make_ready_future()` creates an already-completed future\n\n---\n\n## Task Graphs\n\nFor complex dependency patterns, build a task graph:\n\n<!-- @example graph_example.cpp -->\n\n**Diamond dependency pattern:**\n\n```cpp\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n\n//         A\n//        / \\\n//       B   C\n//        \\ /\n//         D\ndispenso::Graph graph;\n\ndispenso::Node& A = graph.addNode([&]() { r[0] = 1.0f; });\ndispenso::Node& B = graph.addNode([&]() { r[1] = r[0] * 2.0f; });\ndispenso::Node& C = graph.addNode([&]() { r[2] = r[0] + 5.0f; });\ndispenso::Node& D = graph.addNode([&]() { r[3] = r[1] + r[2]; });\n\nB.dependsOn(A);\nC.dependsOn(A);\nD.dependsOn(B, C);\n\nsetAllNodesIncomplete(graph);\ndispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\ndispenso::ConcurrentTaskSetExecutor executor;\nexecutor(taskSet, graph);\n```\n\nSee [full example](../examples/graph_example.cpp).\n\nKey points:\n- Use `dependsOn()` to specify prerequisites\n- Multiple executors available: single-thread, parallel_for, ConcurrentTaskSet\n- Graphs can be re-executed after calling `setAllNodesIncomplete()`\n- Subgraphs help organize large graphs\n\n---\n\n## Pipelines\n\nFor streaming data through stages, use pipelines:\n\n<!-- @example pipeline_example.cpp -->\n\n**3-stage pipeline (generator -> transform -> sink):**\n\n```cpp\n#include <dispenso/pipeline.h>\n\nstd::vector<int> results;\nint counter = 0;\n\ndispenso::pipeline(\n    // Stage 1: Generator - produces values\n    [&counter]() -> dispenso::OpResult<int> {\n      if (counter >= 10) {\n        return {}; // Empty result signals end of input\n      }\n      return counter++;\n    },\n    // Stage 2: Transform - squares the value\n    [](int value) { return value * value; },\n    // Stage 3: Sink - collects results\n    [&results](int value) { results.push_back(value); });\n```\n\nSee [full example](../examples/pipeline_example.cpp).\n\nKey points:\n- Generator stage produces values (returns `OpResult<T>` or `std::optional<T>`)\n- Transform stages process values (can filter by returning empty result)\n- Sink stage consumes final values\n- Use `stage()` with a limit for parallel stages\n\n---\n\n## Thread-Safe Containers\n\n### ConcurrentVector\n\nA vector that supports concurrent push_back and growth:\n\n<!-- @example concurrent_vector_example.cpp -->\n\n**Concurrent push_back from multiple threads:**\n\n```cpp\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/parallel_for.h>\n\ndispenso::ConcurrentVector<int> vec;\n\ndispenso::parallel_for(0, 1000, [&vec](size_t i) { vec.push_back(static_cast<int>(i)); });\n```\n\n**Iterator stability during concurrent modification:**\n\n```cpp\ndispenso::ConcurrentVector<int> vec;\nvec.push_back(1);\nvec.push_back(2);\nvec.push_back(3);\n\nauto it = vec.begin();\nint& firstElement = *it;\n\n// Push more elements concurrently\ndispenso::parallel_for(0, 100, [&vec](size_t i) { vec.push_back(static_cast<int>(i + 100)); });\n\n// Original iterator and reference are still valid\nassert(*it == 1);\nassert(firstElement == 1);\n```\n\nSee [full example](../examples/concurrent_vector_example.cpp).\n\nKey points:\n- Iterators and references remain stable during growth\n- Use `grow_by()` for efficient batch insertion\n- Reserve capacity upfront when size is known\n- Not all operations are concurrent-safe (see docs)\n\n---\n\n## Synchronization Primitives\n\n### Latch\n\nA one-shot barrier for thread synchronization:\n\n<!-- @example latch_example.cpp -->\n\n**count_down + wait pattern:**\n\n```cpp\n#include <dispenso/latch.h>\n\nconstexpr int kNumWorkers = 3;\ndispenso::Latch workComplete(kNumWorkers);\nstd::vector<int> results(kNumWorkers, 0);\n\ndispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\nfor (int i = 0; i < kNumWorkers; ++i) {\n  taskSet.schedule([&workComplete, &results, i]() {\n    results[static_cast<size_t>(i)] = (i + 1) * 10;\n    workComplete.count_down();  // Signal work is done (non-blocking)\n  });\n}\n\nworkComplete.wait();  // Main thread waits for all workers\n```\n\nSee [full example](../examples/latch_example.cpp).\n\nKey points:\n- `arrive_and_wait()` decrements and blocks\n- `count_down()` decrements without blocking\n- `wait()` blocks without decrementing\n- Cannot be reset (one-shot)\n\n---\n\n## Resource Pooling\n\nManage expensive-to-create resources with `ResourcePool`:\n\n<!-- @example resource_pool_example.cpp -->\n\n**Basic buffer pool with RAII:**\n\n```cpp\n#include <dispenso/resource_pool.h>\n\n// Create a pool of 4 buffers\ndispenso::ResourcePool<Buffer> bufferPool(4, []() { return Buffer(); });\n\ndispenso::parallel_for(0, 100, [&bufferPool](size_t i) {\n  // Acquire a resource from the pool (blocks if none available)\n  auto resource = bufferPool.acquire();\n\n  // Use the resource\n  resource.get().process(static_cast<int>(i));\n\n  // Resource automatically returned to pool when 'resource' goes out of scope\n});\n```\n\nSee [full example](../examples/resource_pool_example.cpp).\n\nKey points:\n- Resources automatically return to pool when RAII wrapper destructs\n- `acquire()` blocks if no resources available\n- Good for database connections, buffers, etc.\n- Can be used to limit concurrency\n\n---\n\n## Next Steps\n\n- Browse the [API Reference](modules.html) for complete documentation\n- Check out the [tests](https://github.com/facebookincubator/dispenso/tree/main/tests)\n  for more usage examples\n- See the [benchmarks](https://github.com/facebookincubator/dispenso/tree/main/benchmarks)\n  for performance testing patterns\n"
  },
  {
    "path": "docs/groups.dox",
    "content": "/**\n * @defgroup group_core Core Components\n * @brief Thread pools and task management fundamentals\n *\n * The core components provide the foundation for all parallel execution in dispenso.\n * This includes the ThreadPool class which is the heart of dispenso, as well as\n * TaskSet for managing groups of related tasks, and supporting types like\n * OnceFunction and Schedulable.\n *\n * ### Example: Using ThreadPool and TaskSet\n * @code\n * #include <dispenso/thread_pool.h>\n * #include <dispenso/task_set.h>\n *\n * // Use the global thread pool\n * dispenso::TaskSet tasks(dispenso::globalThreadPool());\n *\n * // Schedule multiple tasks\n * tasks.schedule([]() { /* task 1 */ });\n * tasks.schedule([]() { /* task 2 */ });\n * tasks.schedule([]() { /* task 3 */ });\n *\n * // Wait for all tasks to complete\n * tasks.wait();\n * @endcode\n */\n\n/**\n * @defgroup group_parallel Parallel Loops\n * @brief Parallel for loops and iteration\n *\n * Functions for performing parallel for loops and parallel iteration over ranges.\n * These provide simple, high-level APIs for data-parallel operations.\n *\n * ### Example: Basic parallel_for\n * @code\n * #include <dispenso/parallel_for.h>\n *\n * std::vector<float> data(1000);\n *\n * // Process elements in parallel\n * dispenso::parallel_for(0, data.size(), [&](size_t i) {\n *     data[i] = std::sin(static_cast<float>(i));\n * });\n * @endcode\n *\n * ### Example: Parallel for_each\n * @code\n * #include <dispenso/for_each.h>\n *\n * std::vector<int> values = {1, 2, 3, 4, 5};\n *\n * dispenso::for_each(values.begin(), values.end(), [](int& v) {\n *     v *= 2;  // Double each value in parallel\n * });\n * @endcode\n */\n\n/**\n * @defgroup group_async Async & Futures\n * @brief Asynchronous execution and future results\n *\n * Futures, async requests, completion events, and timed tasks for asynchronous\n * programming patterns.\n *\n * ### Example: Using Futures\n * @code\n * #include <dispenso/future.h>\n *\n * // Create a future that computes a value asynchronously\n * dispenso::Future<int> future(\n *     []() { return 42; },\n *     dispenso::globalThreadPool()\n * );\n *\n * // Do other work...\n *\n * // Get the result (blocks if not ready)\n * int result = future.get();\n * @endcode\n *\n * ### Example: CompletionEvent for signaling\n * @code\n * #include <dispenso/completion_event.h>\n *\n * dispenso::CompletionEvent event;\n *\n * // In producer thread:\n * event.notify();\n *\n * // In consumer thread:\n * event.wait();  // Blocks until notify() is called\n * @endcode\n */\n\n/**\n * @defgroup group_graph Graphs & Pipelines\n * @brief Task graph execution and pipeline processing\n *\n * Task graphs allow expressing complex dependencies between tasks, while pipelines\n * provide a streaming model for processing data through multiple stages.\n *\n * ### Example: Task Graph with Dependencies\n * @code\n * #include <dispenso/graph.h>\n * #include <dispenso/graph_executor.h>\n *\n * dispenso::Graph graph;\n *\n * // Create nodes\n * auto& nodeA = graph.addNode([]() { /* compute A */ });\n * auto& nodeB = graph.addNode([]() { /* compute B */ });\n * auto& nodeC = graph.addNode([]() { /* uses A and B */ });\n *\n * // C depends on A and B completing first\n * nodeC.dependsOn(nodeA, nodeB);\n *\n * // Execute the graph\n * dispenso::TaskSet tasks(dispenso::globalThreadPool());\n * dispenso::ParallelForExecutor executor;\n * executor(tasks, graph);\n * @endcode\n *\n * ### Example: Pipeline Processing\n * @code\n * #include <dispenso/pipeline.h>\n *\n * int itemIndex = 0;\n *\n * dispenso::pipeline(\n *     // Generator stage: produces items\n *     [&]() -> dispenso::OpResult<int> {\n *         if (itemIndex < 100) return itemIndex++;\n *         return {};  // Empty result signals completion\n *     },\n *     // Transform stage: process in parallel\n *     dispenso::stage([](int x) { return x * 2; }, 4),\n *     // Sink stage: consume results\n *     [](int result) { /* use result */ }\n * );\n * @endcode\n */\n\n/**\n * @defgroup group_containers Concurrent Containers\n * @brief Thread-safe data structures\n *\n * Thread-safe containers including concurrent vectors, object arenas, and\n * resource pools for managing shared data in parallel programs.\n *\n * ### Example: ConcurrentVector\n * @code\n * #include <dispenso/concurrent_vector.h>\n * #include <dispenso/parallel_for.h>\n *\n * dispenso::ConcurrentVector<int> results;\n *\n * dispenso::parallel_for(0, 1000, [&](size_t i) {\n *     // Safe to call from multiple threads simultaneously\n *     results.push_back(static_cast<int>(i * i));\n * });\n * @endcode\n *\n * ### Example: ResourcePool\n * @code\n * #include <dispenso/resource_pool.h>\n *\n * // Pool of 4 reusable connections\n * dispenso::ResourcePool<Connection> pool(4, []() {\n *     return Connection();\n * });\n *\n * {\n *     auto conn = pool.acquire();  // Blocks if none available\n *     conn->doWork();\n * }  // Connection automatically returned to pool\n * @endcode\n */\n\n/**\n * @defgroup group_sync Synchronization\n * @brief Synchronization primitives\n *\n * Locks, latches, and other synchronization primitives for coordinating\n * between threads.\n *\n * ### Example: Latch for Thread Coordination\n * @code\n * #include <dispenso/latch.h>\n * #include <dispenso/parallel_for.h>\n *\n * dispenso::Latch latch(4);  // Wait for 4 threads\n *\n * dispenso::parallel_for(0, 4, [&](size_t) {\n *     // Do initialization work...\n *     latch.arrive_and_wait();  // Synchronize before continuing\n *     // All threads proceed together from here\n * });\n * @endcode\n *\n * ### Example: RWLock for Reader/Writer Access\n * @code\n * #include <dispenso/rw_lock.h>\n *\n * dispenso::RWLock lock;\n * std::vector<int> sharedData;\n *\n * // Reader (multiple allowed concurrently)\n * {\n *     std::shared_lock<dispenso::RWLock> guard(lock);\n *     int value = sharedData[0];\n * }\n *\n * // Writer (exclusive access)\n * {\n *     std::unique_lock<dispenso::RWLock> guard(lock);\n *     sharedData.push_back(42);\n * }\n * @endcode\n */\n\n/**\n * @defgroup group_alloc Allocators\n * @brief Memory allocation utilities\n *\n * Pool allocators and small buffer allocators for efficient memory management\n * in parallel programs.\n *\n * ### Example: SmallBufferAllocator\n * @code\n * #include <dispenso/small_buffer_allocator.h>\n *\n * // Allocator for 64-byte buffers\n * dispenso::SmallBufferAllocator<64> allocator;\n *\n * // Allocate and deallocate efficiently\n * char* buffer = allocator.alloc();\n * // ... use buffer ...\n * allocator.dealloc(buffer);\n * @endcode\n *\n * ### Example: PoolAllocator with Custom Backing\n * @code\n * #include <dispenso/pool_allocator.h>\n *\n * dispenso::PoolAllocator allocator(\n *     1024,        // chunk size\n *     1024 * 1024, // slab size\n *     [](size_t n) { return malloc(n); },\n *     [](void* p) { free(p); }\n * );\n *\n * char* chunk = allocator.alloc();\n * // ... use chunk ...\n * allocator.dealloc(chunk);\n * @endcode\n */\n\n/**\n * @defgroup group_util Utilities\n * @brief Platform abstractions and helper utilities\n *\n * Platform-specific abstractions, timing utilities, thread identification,\n * priority control, and thread sanitizer annotations.\n *\n * ### Example: Timing\n * @code\n * #include <dispenso/timing.h>\n *\n * double start = dispenso::getTime();\n * // ... do work ...\n * double elapsed = dispenso::getTime() - start;\n * @endcode\n *\n * ### Example: Thread Priority\n * @code\n * #include <dispenso/priority.h>\n *\n * // Set current thread to high priority\n * dispenso::setCurrentThreadPriority(dispenso::ThreadPriority::kHigh);\n *\n * // Get current priority\n * auto priority = dispenso::getCurrentThreadPriority();\n * @endcode\n */\n"
  },
  {
    "path": "docs/header.html",
    "content": "<!-- HTML header for generated pages -->\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"$langISO\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=11\"/>\n<meta name=\"generator\" content=\"Doxygen $doxygenversion\"/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->\n<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->\n<link href=\"$relpath^tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<!--BEGIN DISABLE_INDEX-->\n  <!--BEGIN FULL_SIDEBAR-->\n<script type=\"text/javascript\">var page_layout=1;</script>\n  <!--END FULL_SIDEBAR-->\n<!--END DISABLE_INDEX-->\n<script type=\"text/javascript\" src=\"$relpath^jquery.js\"></script>\n<script type=\"text/javascript\" src=\"$relpath^dynsections.js\"></script>\n$treeview\n$search\n$mathjax\n$darkmode\n<link href=\"$relpath^$stylesheet\" rel=\"stylesheet\" type=\"text/css\" />\n$extrastylesheet\n</head>\n<body>\n<!--BEGIN DISABLE_INDEX-->\n  <!--BEGIN FULL_SIDEBAR-->\n<div id=\"side-nav\" class=\"ui-resizable side-nav-resizable\"><!-- do not remove this div, it is closed by doxygen! -->\n  <!--END FULL_SIDEBAR-->\n<!--END DISABLE_INDEX-->\n\n<div id=\"top\"><!-- do not remove this div, it is closed by doxygen! -->\n\n<!--BEGIN TITLEAREA-->\n<div id=\"titlearea\">\n<table cellspacing=\"0\" cellpadding=\"0\">\n <tbody>\n <tr id=\"projectrow\">\n  <!--BEGIN PROJECT_LOGO-->\n  <td id=\"projectlogo\"><img alt=\"Logo\" src=\"$relpath^$projectlogo\"/></td>\n  <!--END PROJECT_LOGO-->\n  <!--BEGIN PROJECT_NAME-->\n  <td id=\"projectalign\">\n   <div id=\"projectname\">$projectname<!--BEGIN PROJECT_NUMBER--><span id=\"projectnumber\">&#160;$projectnumber</span><!--END PROJECT_NUMBER-->\n   </div>\n   <!--BEGIN PROJECT_BRIEF--><div id=\"projectbrief\">$projectbrief</div><!--END PROJECT_BRIEF-->\n  </td>\n  <!--END PROJECT_NAME-->\n  <!--BEGIN !PROJECT_NAME-->\n   <!--BEGIN PROJECT_BRIEF-->\n    <td>\n    <div id=\"projectbrief\">$projectbrief</div>\n    </td>\n   <!--END PROJECT_BRIEF-->\n  <!--END !PROJECT_NAME-->\n  <!--BEGIN DISABLE_INDEX-->\n   <!--BEGIN SEARCHENGINE-->\n     <!--BEGIN !FULL_SIDEBAR-->\n    <td>$searchbox</td>\n     <!--END !FULL_SIDEBAR-->\n   <!--END SEARCHENGINE-->\n  <!--END DISABLE_INDEX-->\n </tr>\n  <!--BEGIN SEARCHENGINE-->\n   <!--BEGIN FULL_SIDEBAR-->\n    <tr><td colspan=\"2\">$searchbox</td></tr>\n   <!--END FULL_SIDEBAR-->\n  <!--END SEARCHENGINE-->\n </tbody>\n</table>\n</div>\n<!--END TITLEAREA-->\n<!-- end header part -->\n"
  },
  {
    "path": "docs/mainpage.md",
    "content": "# Dispenso {#mainpage}\n\n**A high-performance C++14 library for task parallelism**\n\nDispenso provides mechanisms for thread pools, task sets, parallel for loops,\nfutures, pipelines, task graphs, and more.\n\n## Quick Start\n\n```cpp\n#include <dispenso/parallel_for.h>\n\ndispenso::parallel_for(0, 1000, [](size_t i) {\n    // Process item i in parallel\n});\n```\n\n## Getting Started\n\nNew to dispenso? Start with the @ref getting_started \"Getting Started Guide\" for\nstep-by-step tutorials and working examples.\n\n## API Modules\n\n- @ref group_core \"Core Components\" - Thread pools and task sets\n- @ref group_parallel \"Parallel Loops\" - parallel_for and for_each\n- @ref group_async \"Async & Futures\" - Futures and async operations\n- @ref group_graph \"Graphs & Pipelines\" - Task graphs and pipelines\n- @ref group_containers \"Concurrent Containers\" - Thread-safe data structures\n- @ref group_sync \"Synchronization\" - Locks, latches, and events\n- @ref group_alloc \"Allocators\" - Memory allocation utilities\n- @ref group_util \"Utilities\" - Platform, timing, and helpers\n\n## Resources\n\n- [GitHub Repository](https://github.com/facebookincubator/dispenso)\n"
  },
  {
    "path": "docs/migrating_from_openmp.md",
    "content": "# Migrating from OpenMP to Dispenso\n\nThis guide helps you migrate parallel code from OpenMP to dispenso. Dispenso offers\nseveral advantages over OpenMP for many use cases, including better nested parallelism,\nexplicit thread pool control, and sanitizer-clean code.\n\n## Why Migrate?\n\n| Aspect | OpenMP | Dispenso |\n|--------|--------|----------|\n| **Nested parallelism** | Can cause thread explosion | Work-stealing prevents oversubscription |\n| **Thread pool control** | Implicit, global | Explicit, multiple pools supported |\n| **Sanitizer support** | Often problematic with TSAN | Clean with ASAN/TSAN |\n| **Portability** | Requires compiler support | Pure C++14, any compiler |\n| **Futures** | Not available | Full futures API |\n| **Task graphs** | Limited | Rich graph support with partial re-execution |\n\n## Quick Reference\n\n| OpenMP | Dispenso |\n|--------|----------|\n| `#pragma omp parallel for` | `dispenso::parallel_for()` |\n| `#pragma omp parallel for reduction(+:sum)` | `dispenso::parallel_for()` with `ParForChunking` + local accumulators |\n| `#pragma omp critical` | `std::mutex` or `dispenso::RWLock` |\n| `#pragma omp task` | `dispenso::TaskSet::schedule()` |\n| `#pragma omp taskwait` | `dispenso::TaskSet::wait()` |\n| `#pragma omp single` | Execute outside parallel region |\n| `omp_get_num_threads()` | `pool.numThreads()` |\n| `omp_get_thread_num()` | Not directly available (usually not needed) |\n\n## Basic Parallel For\n\n### OpenMP\n```cpp\n#pragma omp parallel for\nfor (int i = 0; i < N; ++i) {\n    process(data[i]);\n}\n```\n\n### Dispenso\n```cpp\n#include <dispenso/parallel_for.h>\n\ndispenso::parallel_for(0, N, [&](size_t i) {\n    process(data[i]);\n});\n```\n\n## Parallel For with Reduction\n\n### OpenMP\n```cpp\ndouble sum = 0.0;\n#pragma omp parallel for reduction(+:sum)\nfor (int i = 0; i < N; ++i) {\n    sum += compute(data[i]);\n}\n```\n\n### Dispenso\n\nDispenso doesn't have built-in reduction syntax, but you can achieve the same result\nwith thread-local accumulators:\n\n```cpp\n#include <dispenso/parallel_for.h>\n\nstd::atomic<double> sum{0.0};\ndispenso::parallel_for(0, N, [&](size_t i) {\n    // For simple reductions, atomic works well\n    double val = compute(data[i]);\n    double expected = sum.load();\n    while (!sum.compare_exchange_weak(expected, expected + val)) {}\n});\n```\n\nFor better performance with many updates, use chunked iteration with local accumulators:\n\n```cpp\n#include <dispenso/parallel_for.h>\n#include <mutex>\n\ndouble sum = 0.0;\nstd::mutex sumMutex;\n\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kStatic),\n    [&](size_t begin, size_t end) {\n        double localSum = 0.0;\n        for (size_t i = begin; i < end; ++i) {\n            localSum += compute(data[i]);\n        }\n        std::lock_guard<std::mutex> lock(sumMutex);\n        sum += localSum;\n    });\n```\n\nOr use the state-per-thread overload of `parallel_for`:\n\n```cpp\n#include <dispenso/parallel_for.h>\n\nstd::vector<double> partialSums;\ndispenso::parallel_for(\n    partialSums,\n    []() { return 0.0; },  // Initialize each thread's state\n    size_t{0}, static_cast<size_t>(N),\n    [&](double& localSum, size_t begin, size_t end) {\n        for (size_t i = begin; i < end; ++i) {\n            localSum += compute(data[i]);\n        }\n    });\n\ndouble sum = 0.0;\nfor (double partial : partialSums) {\n    sum += partial;\n}\n```\n\n## Nested Parallel Loops\n\nThis is where dispenso shines. OpenMP can create exponentially many threads with\nnested parallel regions, while dispenso's work-stealing handles this gracefully.\n\n### OpenMP (Problematic)\n```cpp\n// WARNING: With OpenMP, this can create numThreads^2 threads!\n#pragma omp parallel for\nfor (int i = 0; i < M; ++i) {\n    #pragma omp parallel for\n    for (int j = 0; j < N; ++j) {\n        process(i, j);\n    }\n}\n```\n\n### Dispenso (Safe)\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Dispenso uses work-stealing - nested parallelism is safe and efficient\ndispenso::parallel_for(0, M, [&](size_t i) {\n    dispenso::parallel_for(0, N, [&](size_t j) {\n        process(i, j);\n    });\n});\n```\n\nWith dispenso, the total number of threads is bounded by the thread pool size,\nregardless of nesting depth.\n\n## Critical Sections\n\n### OpenMP\n```cpp\n#pragma omp parallel for\nfor (int i = 0; i < N; ++i) {\n    double val = compute(data[i]);\n    #pragma omp critical\n    {\n        results.push_back(val);\n    }\n}\n```\n\n### Dispenso\n```cpp\n#include <dispenso/parallel_for.h>\n#include <mutex>\n\nstd::mutex resultsMutex;\ndispenso::parallel_for(0, N, [&](size_t i) {\n    double val = compute(data[i]);\n    std::lock_guard<std::mutex> lock(resultsMutex);\n    results.push_back(val);\n});\n```\n\nOr use `dispenso::ConcurrentVector` to avoid locking entirely:\n\n```cpp\n#include <dispenso/parallel_for.h>\n#include <dispenso/concurrent_vector.h>\n\ndispenso::ConcurrentVector<double> results;\ndispenso::parallel_for(0, N, [&](size_t i) {\n    double val = compute(data[i]);\n    results.push_back(val);\n});\n```\n\n## Task Parallelism\n\n### OpenMP\n```cpp\n#pragma omp parallel\n{\n    #pragma omp single\n    {\n        #pragma omp task\n        taskA();\n\n        #pragma omp task\n        taskB();\n\n        #pragma omp taskwait\n        // A and B are done\n\n        #pragma omp task\n        taskC();\n    }\n}\n```\n\n### Dispenso\n```cpp\n#include <dispenso/task_set.h>\n\ndispenso::TaskSet tasks(dispenso::globalThreadPool());\n\ntasks.schedule(taskA);\ntasks.schedule(taskB);\ntasks.wait();  // A and B are done\n\ntasks.schedule(taskC);\n// TaskSet destructor waits for C\n```\n\n## Controlling Thread Count\n\n### OpenMP\n```cpp\nomp_set_num_threads(4);\n// or\n#pragma omp parallel for num_threads(4)\n```\n\n### Dispenso\n\nCreate a thread pool with the desired number of threads:\n\n```cpp\n#include <dispenso/thread_pool.h>\n#include <dispenso/parallel_for.h>\n\ndispenso::ThreadPool pool(4);  // 4 threads\n\ndispenso::parallel_for(pool, 0, N, [&](size_t i) {\n    process(data[i]);\n});\n```\n\nOr use `ParForOptions` to limit parallelism:\n\n```cpp\ndispenso::ParForOptions options;\noptions.maxThreads = 4;\n\ndispenso::parallel_for(options, 0, N, [&](size_t i) {\n    process(data[i]);\n});\n```\n\n## Conditional Parallelism\n\n### OpenMP\n```cpp\n#pragma omp parallel for if(N > 1000)\nfor (int i = 0; i < N; ++i) {\n    process(data[i]);\n}\n```\n\n### Dispenso\n```cpp\nif (N > 1000) {\n    dispenso::parallel_for(0, N, [&](size_t i) {\n        process(data[i]);\n    });\n} else {\n    for (size_t i = 0; i < N; ++i) {\n        process(data[i]);\n    }\n}\n```\n\nOr use `minItemsPerChunk` to let dispenso decide:\n\n```cpp\ndispenso::ParForOptions options;\noptions.minItemsPerChunk = 100;  // Don't parallelize if fewer than 100 items per thread\n\ndispenso::parallel_for(options, 0, N, [&](size_t i) {\n    process(data[i]);\n});\n```\n\n## Static vs Dynamic Scheduling\n\n### OpenMP\n```cpp\n// Static scheduling\n#pragma omp parallel for schedule(static)\nfor (int i = 0; i < N; ++i) { ... }\n\n// Dynamic scheduling\n#pragma omp parallel for schedule(dynamic)\nfor (int i = 0; i < N; ++i) { ... }\n```\n\n### Dispenso\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Static-like chunking\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kStatic),\n    [&](size_t begin, size_t end) {\n        for (size_t i = begin; i < end; ++i) {\n            process(data[i]);\n        }\n    });\n\n// Dynamic-like (auto) chunking - adapts to workload\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kAuto),\n    [&](size_t begin, size_t end) {\n        for (size_t i = begin; i < end; ++i) {\n            process(data[i]);\n        }\n    });\n```\n\n## Thread-Local Storage\n\n### OpenMP\n```cpp\n#pragma omp threadprivate(myThreadLocalVar)\nint myThreadLocalVar;\n\n#pragma omp parallel\n{\n    myThreadLocalVar = omp_get_thread_num();\n    // use myThreadLocalVar\n}\n```\n\n### Dispenso\n\nUse C++11 `thread_local` or the state-per-thread `parallel_for` overload:\n\n```cpp\n// Option 1: C++ thread_local\nthread_local int myThreadLocalVar;\n\ndispenso::parallel_for(0, N, [&](size_t i) {\n    // myThreadLocalVar is thread-local\n});\n\n// Option 2: State-per-thread parallel_for\nstd::vector<MyState> states;\ndispenso::parallel_for(\n    states,\n    []() { return MyState{}; },  // Initialize\n    0, N,\n    [&](MyState& state, size_t begin, size_t end) {\n        // 'state' is unique to this thread\n    });\n```\n\n## Common Pitfalls When Migrating\n\n### 1. Lambda Captures\n\nOpenMP uses shared variables by default. With dispenso, be explicit about captures:\n\n```cpp\n// OpenMP - x is shared by default\nint x = 0;\n#pragma omp parallel for\nfor (int i = 0; i < N; ++i) {\n    // x is shared\n}\n\n// Dispenso - be explicit\nint x = 0;\ndispenso::parallel_for(0, N, [&x](size_t i) {  // Capture x by reference\n    // x is shared\n});\n```\n\n### 2. Index Types\n\nOpenMP typically uses `int`. Dispenso uses `size_t`:\n\n```cpp\n// OpenMP\n#pragma omp parallel for\nfor (int i = 0; i < N; ++i) { ... }\n\n// Dispenso - use size_t\ndispenso::parallel_for(size_t{0}, static_cast<size_t>(N), [&](size_t i) {\n    // ...\n});\n```\n\n### 3. Return Values\n\nOpenMP parallel regions don't return values. With dispenso futures, you can:\n\n```cpp\n#include <dispenso/future.h>\n\nauto future = dispenso::async([]() {\n    return expensiveComputation();\n});\n\n// Do other work...\n\nint result = future.get();  // Get the result\n```\n\n## Performance Tips\n\n1. **Use chunked ranges** for better cache locality when iteration order doesn't matter\n\n2. **Avoid over-synchronization** - dispenso's `ConcurrentVector` is often faster than\n   mutex-protected `std::vector`\n\n3. **Reuse thread pools** - creating pools is expensive; create once and reuse\n\n4. **Consider static chunking** for uniform workloads, auto chunking for variable workloads\n\n## Further Reading\n\n- [Dispenso Documentation](https://facebookincubator.github.io/dispenso)\n- [Getting Started Guide](getting_started.md)\n- [parallel_for API Reference](https://facebookincubator.github.io/dispenso/group__parallel.html)\n"
  },
  {
    "path": "docs/migrating_from_tbb.md",
    "content": "# Migrating from Intel TBB to Dispenso\n\nThis guide helps you migrate parallel code from Intel Threading Building Blocks (TBB)\nto dispenso. While TBB has more features overall, dispenso offers advantages in\nseveral areas and provides a simpler, more focused API.\n\n## Why Migrate?\n\n| Aspect | TBB | Dispenso |\n|--------|-----|----------|\n| **Sanitizer support** | Often problematic with ASAN/TSAN | Clean with all sanitizers |\n| **Futures** | Not available | Full std::experimental::future-like API |\n| **API complexity** | Large, complex API | Focused, simpler API |\n| **Dependencies** | Heavy library | Minimal dependencies |\n| **Non-Intel hardware** | May not be optimized | Platform-neutral implementation |\n| **Nested parallelism** | Good | Excellent (work-stealing optimized) |\n\n## Quick Reference\n\n| TBB | Dispenso |\n|-----|----------|\n| `tbb::parallel_for` | `dispenso::parallel_for` |\n| `tbb::parallel_reduce` | `dispenso::parallel_for` with state |\n| `tbb::parallel_for_each` | `dispenso::for_each` |\n| `tbb::task_group` | `dispenso::TaskSet` |\n| `tbb::task_group::run` | `dispenso::TaskSet::schedule` |\n| `tbb::task_group::wait` | `dispenso::TaskSet::wait` |\n| `tbb::concurrent_vector` | `dispenso::ConcurrentVector` |\n| `tbb::flow::graph` | `dispenso::Graph` |\n| `tbb::global_control` | `dispenso::ThreadPool` configuration |\n| `tbb::task_arena` | `dispenso::ThreadPool` (multiple pools) |\n\n## Parallel For with Index\n\n### TBB\n```cpp\n#include <tbb/parallel_for.h>\n#include <tbb/blocked_range.h>\n\ntbb::parallel_for(tbb::blocked_range<size_t>(0, N),\n    [&](const tbb::blocked_range<size_t>& range) {\n        for (size_t i = range.begin(); i < range.end(); ++i) {\n            process(data[i]);\n        }\n    });\n```\n\n### Dispenso\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Simple form - per-element\ndispenso::parallel_for(0, N, [&](size_t i) {\n    process(data[i]);\n});\n\n// Chunked form - like TBB's blocked_range\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kAuto),\n    [&](size_t begin, size_t end) {\n        for (size_t i = begin; i < end; ++i) {\n            process(data[i]);\n        }\n    });\n```\n\n## Parallel Reduce\n\n### TBB\n```cpp\n#include <tbb/parallel_reduce.h>\n#include <tbb/blocked_range.h>\n\ndouble sum = tbb::parallel_reduce(\n    tbb::blocked_range<size_t>(0, N),\n    0.0,\n    [&](const tbb::blocked_range<size_t>& range, double init) {\n        for (size_t i = range.begin(); i < range.end(); ++i) {\n            init += compute(data[i]);\n        }\n        return init;\n    },\n    std::plus<double>()\n);\n```\n\n### Dispenso\n\nUse the state-per-thread `parallel_for` overload:\n\n```cpp\n#include <dispenso/parallel_for.h>\n\nstd::vector<double> partialSums;\ndispenso::parallel_for(\n    partialSums,\n    []() { return 0.0; },  // Initialize each thread's accumulator\n    size_t{0}, N,\n    [&](double& localSum, size_t begin, size_t end) {\n        for (size_t i = begin; i < end; ++i) {\n            localSum += compute(data[i]);\n        }\n    });\n\ndouble sum = 0.0;\nfor (double partial : partialSums) {\n    sum += partial;\n}\n```\n\n## Parallel For Each\n\n### TBB\n```cpp\n#include <tbb/parallel_for_each.h>\n\nstd::vector<Item> items;\ntbb::parallel_for_each(items.begin(), items.end(), [](Item& item) {\n    process(item);\n});\n```\n\n### Dispenso\n```cpp\n#include <dispenso/for_each.h>\n\nstd::vector<Item> items;\ndispenso::for_each(items.begin(), items.end(), [](Item& item) {\n    process(item);\n});\n```\n\n## Task Groups\n\n### TBB\n```cpp\n#include <tbb/task_group.h>\n\ntbb::task_group tg;\ntg.run([]{ taskA(); });\ntg.run([]{ taskB(); });\ntg.wait();\n\ntg.run([]{ taskC(); });\ntg.wait();\n```\n\n### Dispenso\n```cpp\n#include <dispenso/task_set.h>\n\ndispenso::TaskSet tasks(dispenso::globalThreadPool());\ntasks.schedule([]{ taskA(); });\ntasks.schedule([]{ taskB(); });\ntasks.wait();\n\ntasks.schedule([]{ taskC(); });\ntasks.wait();\n```\n\nFor recursive task parallelism (where tasks spawn more tasks), use `ConcurrentTaskSet`:\n\n```cpp\n#include <dispenso/task_set.h>\n\ndispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n\nvoid recursiveWork(dispenso::ConcurrentTaskSet& tasks, int depth) {\n    if (depth == 0) return;\n\n    tasks.schedule([&tasks, depth]{ recursiveWork(tasks, depth - 1); });\n    tasks.schedule([&tasks, depth]{ recursiveWork(tasks, depth - 1); });\n}\n\nrecursiveWork(tasks, 10);\ntasks.wait();\n```\n\n## Concurrent Vector\n\n### TBB\n```cpp\n#include <tbb/concurrent_vector.h>\n\ntbb::concurrent_vector<int> vec;\n\ntbb::parallel_for(size_t(0), N, [&](size_t i) {\n    vec.push_back(compute(i));\n});\n\n// Access elements\nfor (const auto& val : vec) {\n    use(val);\n}\n```\n\n### Dispenso\n\nDispenso's `ConcurrentVector` has a superset of TBB's API:\n\n```cpp\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/parallel_for.h>\n\ndispenso::ConcurrentVector<int> vec;\n\ndispenso::parallel_for(size_t{0}, N, [&](size_t i) {\n    vec.push_back(compute(i));\n});\n\n// Access elements - same as TBB\nfor (const auto& val : vec) {\n    use(val);\n}\n```\n\nAdditional dispenso features:\n\n```cpp\n// Grow by multiple elements efficiently\nvec.grow_by(100);  // Add 100 default-constructed elements\n\n// Grow with generator (avoids repeated locking)\nvec.grow_by_generator(100, [i = 0]() mutable { return i++; });\n```\n\n## Task Arenas / Thread Pool Control\n\n### TBB\n```cpp\n#include <tbb/task_arena.h>\n#include <tbb/global_control.h>\n\n// Limit global parallelism\ntbb::global_control gc(tbb::global_control::max_allowed_parallelism, 4);\n\n// Or use arena for isolated execution\ntbb::task_arena arena(4);  // 4 threads\narena.execute([&] {\n    tbb::parallel_for(...);\n});\n```\n\n### Dispenso\n\nCreate explicit thread pools:\n\n```cpp\n#include <dispenso/thread_pool.h>\n#include <dispenso/parallel_for.h>\n\n// Create a pool with 4 threads\ndispenso::ThreadPool pool(4);\n\n// Use the pool for parallel work\ndispenso::parallel_for(pool, 0, N, [&](size_t i) {\n    process(data[i]);\n});\n\n// Or use TaskSet with specific pool\ndispenso::TaskSet tasks(pool);\ntasks.schedule(work);\n```\n\nMultiple pools can coexist for different workloads:\n\n```cpp\ndispenso::ThreadPool computePool(8);   // For CPU-bound work\ndispenso::ThreadPool ioPool(2);        // For I/O-bound work\n\ndispenso::parallel_for(computePool, 0, N, compute);\ndispenso::parallel_for(ioPool, 0, M, ioWork);\n```\n\n## Flow Graphs\n\n### TBB\n```cpp\n#include <tbb/flow_graph.h>\n\ntbb::flow::graph g;\n\ntbb::flow::function_node<int, int> nodeA(g, tbb::flow::unlimited,\n    [](int v) { return processA(v); });\ntbb::flow::function_node<int, int> nodeB(g, tbb::flow::unlimited,\n    [](int v) { return processB(v); });\n\ntbb::flow::make_edge(nodeA, nodeB);\n\nnodeA.try_put(input);\ng.wait_for_all();\n```\n\n### Dispenso\n\nDispenso's `Graph` is optimized for task DAGs with potential partial re-execution:\n\n```cpp\n#include <dispenso/graph.h>\n\ndispenso::Graph graph;\n\nauto& nodeA = graph.addNode([]{ processA(); });\nauto& nodeB = graph.addNode([]{ processB(); });\nauto& nodeC = graph.addNode([]{ processC(); });\n\n// Define dependencies\nnodeB.dependsOn(nodeA);\nnodeC.dependsOn(nodeA);\n\n// Execute the graph\ndispenso::execute(graph, dispenso::globalThreadPool());\n\n// For repeated execution with partial updates:\nnodeA.setIncomplete();  // Mark as needing re-execution\ndispenso::execute(graph, dispenso::globalThreadPool());  // Only re-runs A and dependents\n```\n\n## Futures (Dispenso Advantage)\n\nTBB doesn't have a futures interface. Dispenso provides one:\n\n```cpp\n#include <dispenso/future.h>\n\n// Async computation\ndispenso::Future<int> future = dispenso::async([]() {\n    return expensiveComputation();\n});\n\n// Do other work while computation runs...\n\n// Get result (blocks if not ready)\nint result = future.get();\n\n// Chaining with .then()\nauto future2 = dispenso::async([]{ return 42; })\n    .then([](int x) { return x * 2; })\n    .then([](int x) { return std::to_string(x); });\n\nstd::string result = future2.get();  // \"84\"\n\n// Combining futures\nauto f1 = dispenso::async([]{ return computeA(); });\nauto f2 = dispenso::async([]{ return computeB(); });\n\nauto combined = dispenso::when_all(f1, f2).then([](auto&& tuple) {\n    return std::get<0>(tuple).get() + std::get<1>(tuple).get();\n});\n```\n\n## Pipelines\n\n### TBB\n```cpp\n#include <tbb/pipeline.h>\n\ntbb::parallel_pipeline(\n    maxTokens,\n    tbb::make_filter<void, Data>(tbb::filter::serial_in_order,\n        [&](tbb::flow_control& fc) -> Data {\n            if (done) { fc.stop(); return {}; }\n            return readInput();\n        }) &\n    tbb::make_filter<Data, Data>(tbb::filter::parallel,\n        [](Data d) { return process(d); }) &\n    tbb::make_filter<Data, void>(tbb::filter::serial_in_order,\n        [](Data d) { writeOutput(d); })\n);\n```\n\n### Dispenso\n\nDispenso pipelines are simpler to construct:\n\n```cpp\n#include <dispenso/pipeline.h>\n\ndispenso::pipeline(\n    dispenso::globalThreadPool(),\n    // Stage 1: serial input\n    dispenso::stage([]() -> std::optional<Data> {\n        if (done) return std::nullopt;\n        return readInput();\n    }, 1),  // 1 = serial\n    // Stage 2: parallel processing\n    dispenso::stage([](Data d) { return process(d); }, 0),  // 0 = parallel\n    // Stage 3: serial output\n    dispenso::stage([](Data d) { writeOutput(d); }, 1)  // 1 = serial\n);\n```\n\n## Partitioners / Chunking\n\n### TBB\n```cpp\n// Auto partitioner (default)\ntbb::parallel_for(range, body, tbb::auto_partitioner());\n\n// Static partitioner\ntbb::parallel_for(range, body, tbb::static_partitioner());\n\n// Affinity partitioner (cache-friendly)\ntbb::affinity_partitioner ap;\ntbb::parallel_for(range, body, ap);\n```\n\n### Dispenso\n```cpp\n#include <dispenso/parallel_for.h>\n\n// Auto chunking (like auto_partitioner)\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kAuto),\n    body);\n\n// Static chunking (like static_partitioner)\ndispenso::parallel_for(\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kStatic),\n    body);\n```\n\n## Spin Mutexes\n\n### TBB\n```cpp\n#include <tbb/spin_mutex.h>\n\ntbb::spin_mutex mutex;\n\n{\n    tbb::spin_mutex::scoped_lock lock(mutex);\n    // Critical section\n}\n```\n\n### Dispenso\n```cpp\n#include <dispenso/rw_lock.h>\n#include <mutex>\n\n// For exclusive access, use std::mutex or dispenso::RWLock\nstd::mutex mutex;\n{\n    std::lock_guard<std::mutex> lock(mutex);\n    // Critical section\n}\n\n// For read-heavy workloads, use RWLock\ndispenso::RWLock rwLock;\n{\n    dispenso::RWLock::ReadGuard rlock(rwLock);\n    // Read-only access\n}\n{\n    dispenso::RWLock::WriteGuard wlock(rwLock);\n    // Exclusive write access\n}\n```\n\n## Common Migration Patterns\n\n### Pattern 1: Replace blocked_range with makeChunkedRange\n\n```cpp\n// TBB\ntbb::parallel_for(tbb::blocked_range<size_t>(0, N, grainSize), body);\n\n// Dispenso\ndispenso::ParForOptions options;\noptions.minItemsPerChunk = grainSize;\ndispenso::parallel_for(options,\n    dispenso::makeChunkedRange(0, N, dispenso::ParForChunking::kStatic),\n    body);\n```\n\n### Pattern 2: Replace task_group recursion with ConcurrentTaskSet\n\n```cpp\n// TBB\nvoid recursive(tbb::task_group& tg, int depth) {\n    if (depth == 0) return;\n    tg.run([&tg, depth]{ recursive(tg, depth-1); });\n    tg.run([&tg, depth]{ recursive(tg, depth-1); });\n}\n\n// Dispenso\nvoid recursive(dispenso::ConcurrentTaskSet& tasks, int depth) {\n    if (depth == 0) return;\n    tasks.schedule([&tasks, depth]{ recursive(tasks, depth-1); });\n    tasks.schedule([&tasks, depth]{ recursive(tasks, depth-1); });\n}\n```\n\n### Pattern 3: Combining parallel_for with futures\n\n```cpp\n// Dispenso allows mixing paradigms easily\nauto future = dispenso::async([&]() {\n    dispenso::parallel_for(0, N, [&](size_t i) {\n        process(data[i]);\n    });\n    return computeResult(data);\n});\n\n// Do other work...\nauto result = future.get();\n```\n\n## Performance Considerations\n\n1. **Dispenso is faster for nested loops** - TBB's nested parallelism can have higher\n   overhead; dispenso's work-stealing is optimized for this case\n\n2. **Dispenso has lower overhead for small loops** - simpler scheduling means less\n   overhead for fine-grained parallelism\n\n3. **TBB may be faster for very large, uniform workloads** - TBB's cache-affinity\n   partitioner can help in specific scenarios\n\n4. **Use appropriate chunking** - `kStatic` for uniform work, `kAuto` for variable work\n\n5. **Reuse pools and TaskSets** - creation has overhead; reuse when possible\n\n## Further Reading\n\n- [Dispenso Documentation](https://facebookincubator.github.io/dispenso)\n- [Getting Started Guide](getting_started.md)\n- [Migrating from OpenMP](migrating_from_openmp.md)\n- [API Reference](https://facebookincubator.github.io/dispenso/modules.html)\n"
  },
  {
    "path": "docs/third-party/doxygen-awesome/doxygen-awesome-darkmode-toggle.js",
    "content": "// SPDX-License-Identifier: MIT\n/**\n\nDoxygen Awesome\nhttps://github.com/jothepro/doxygen-awesome-css\n\nCopyright (c) 2021 - 2025 jothepro\n\n*/\n\nclass DoxygenAwesomeDarkModeToggle extends HTMLElement {\n    // SVG icons from https://fonts.google.com/icons\n    // Licensed under the Apache 2.0 license:\n    // https://www.apache.org/licenses/LICENSE-2.0.html\n    static lightModeIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" enable-background=\"new 0 0 24 24\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\" fill=\"#FCBF00\"><rect fill=\"none\" height=\"24\" width=\"24\"/><circle cx=\"12\" cy=\"12\" opacity=\".3\" r=\"3\"/><path d=\"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z\"/></svg>`\n    static darkModeIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" enable-background=\"new 0 0 24 24\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\" fill=\"#FE9700\"><rect fill=\"none\" height=\"24\" width=\"24\"/><path d=\"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z\" opacity=\".3\"/><path d=\"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z\"/></svg>`\n    static title = \"Toggle Light/Dark Mode\"\n\n    static prefersLightModeInDarkModeKey = \"prefers-light-mode-in-dark-mode\"\n    static prefersDarkModeInLightModeKey = \"prefers-dark-mode-in-light-mode\"\n\n    static _staticConstructor = function() {\n        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference)\n        // Update the color scheme when the browsers preference changes\n        // without user interaction on the website.\n        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {\n            DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()\n        })\n        // Update the color scheme when the tab is made visible again.\n        // It is possible that the appearance was changed in another tab\n        // while this tab was in the background.\n        document.addEventListener(\"visibilitychange\", visibilityState => {\n            if (document.visibilityState === 'visible') {\n                DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()\n            }\n        });\n    }()\n\n    static init() {\n        $(function() {\n            $(document).ready(function() {\n                const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle')\n                toggleButton.title = DoxygenAwesomeDarkModeToggle.title\n                toggleButton.updateIcon()\n\n                window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {\n                    toggleButton.updateIcon()\n                })\n                document.addEventListener(\"visibilitychange\", visibilityState => {\n                    if (document.visibilityState === 'visible') {\n                        toggleButton.updateIcon()\n                    }\n                });\n\n                $(document).ready(function(){\n                    document.getElementById(\"MSearchBox\").parentNode.appendChild(toggleButton)\n                })\n                $(window).resize(function(){\n                    document.getElementById(\"MSearchBox\").parentNode.appendChild(toggleButton)\n                })\n            })\n        })\n    }\n\n    constructor() {\n        super();\n        this.onclick=this.toggleDarkMode\n    }\n\n    /**\n     * @returns `true` for dark-mode, `false` for light-mode system preference\n     */\n    static get systemPreference() {\n        return window.matchMedia('(prefers-color-scheme: dark)').matches\n    }\n\n    /**\n     * @returns `true` for dark-mode, `false` for light-mode user preference\n     */\n    static get userPreference() {\n        return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) ||\n        (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))\n    }\n\n    static set userPreference(userPreference) {\n        DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference\n        if(!userPreference) {\n            if(DoxygenAwesomeDarkModeToggle.systemPreference) {\n                localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)\n            } else {\n                localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)\n            }\n        } else {\n            if(!DoxygenAwesomeDarkModeToggle.systemPreference) {\n                localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)\n            } else {\n                localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)\n            }\n        }\n        DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()\n    }\n\n    static enableDarkMode(enable) {\n        if(enable) {\n            DoxygenAwesomeDarkModeToggle.darkModeEnabled = true\n            document.documentElement.classList.add(\"dark-mode\")\n            document.documentElement.classList.remove(\"light-mode\")\n        } else {\n            DoxygenAwesomeDarkModeToggle.darkModeEnabled = false\n            document.documentElement.classList.remove(\"dark-mode\")\n            document.documentElement.classList.add(\"light-mode\")\n        }\n    }\n\n    static onSystemPreferenceChanged() {\n        DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference\n        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)\n    }\n\n    static onUserPreferenceChanged() {\n        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)\n    }\n\n    toggleDarkMode() {\n        DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference\n        this.updateIcon()\n    }\n\n    updateIcon() {\n        if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) {\n            this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon\n        } else {\n            this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon\n        }\n    }\n}\n\ncustomElements.define(\"doxygen-awesome-dark-mode-toggle\", DoxygenAwesomeDarkModeToggle);\n"
  },
  {
    "path": "docs/third-party/doxygen-awesome/doxygen-awesome.css",
    "content": "/* SPDX-License-Identifier: MIT */\n/**\n\nDoxygen Awesome\nhttps://github.com/jothepro/doxygen-awesome-css\n\nCopyright (c) 2021 - 2025 jothepro\n\n*/\n\nhtml {\n    /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */\n    --primary-color: #1779c4;\n    --primary-dark-color: #335c80;\n    --primary-light-color: #70b1e9;\n    --on-primary-color: #ffffff;\n\n    --link-color: var(--primary-color);\n\n    /* page base colors */\n    --page-background-color: #ffffff;\n    --page-foreground-color: #2f4153;\n    --page-secondary-foreground-color: #6f7e8e;\n\n    /* color for all separators on the website: hr, borders, ... */\n    --separator-color: #dedede;\n\n    /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */\n    --border-radius-large: 10px;\n    --border-radius-small: 5px;\n    --border-radius-medium: 8px;\n\n    /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */\n    --spacing-small: 5px;\n    --spacing-medium: 10px;\n    --spacing-large: 16px;\n    --spacing-xlarge: 20px;\n\n    /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */\n    --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075);\n\n    --odd-color: rgba(0,0,0,.028);\n\n    /* font-families. will affect all text on the website\n     * font-family: the normal font for text, headlines, menus\n     * font-family-monospace: used for preformatted text in memtitle, code, fragments\n     */\n    --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;\n    --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;\n\n    /* font sizes */\n    --page-font-size: 15.6px;\n    --navigation-font-size: 14.4px;\n    --toc-font-size: 13.4px;\n    --code-font-size: 14px; /* affects code, fragment */\n    --title-font-size: 22px;\n\n    /* content text properties. These only affect the page content, not the navigation or any other ui elements */\n    --content-line-height: 27px;\n    /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/\n    --content-maxwidth: 1050px;\n    --table-line-height: 24px;\n    --toc-sticky-top: var(--spacing-medium);\n    --toc-width: 200px;\n    --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px);\n\n    /* colors for various content boxes: @warning, @note, @deprecated @bug */\n    --warning-color: #faf3d8;\n    --warning-color-dark: #f3a600;\n    --warning-color-darker: #5f4204;\n    --note-color: #e4f3ff;\n    --note-color-dark: #1879C4;\n    --note-color-darker: #274a5c;\n    --todo-color: #e4dafd;\n    --todo-color-dark: #5b2bdd;\n    --todo-color-darker: #2a0d72;\n    --deprecated-color: #ecf0f3;\n    --deprecated-color-dark: #5b6269;\n    --deprecated-color-darker: #43454a;\n    --bug-color: #f8d1cc;\n    --bug-color-dark: #b61825;\n    --bug-color-darker: #75070f;\n    --invariant-color: #d8f1e3;\n    --invariant-color-dark: #44b86f;\n    --invariant-color-darker: #265532;\n\n    /* blockquote colors */\n    --blockquote-background: #f8f9fa;\n    --blockquote-foreground: #636568;\n\n    /* table colors */\n    --tablehead-background: #f1f1f1;\n    --tablehead-foreground: var(--page-foreground-color);\n\n    /* menu-display: block | none\n     * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible.\n     * `GENERATE_TREEVIEW` MUST be enabled!\n     */\n    --menu-display: block;\n\n    --menu-focus-foreground: var(--on-primary-color);\n    --menu-focus-background: var(--primary-color);\n    --menu-selected-background: rgba(0,0,0,.05);\n\n\n    --header-background: var(--page-background-color);\n    --header-foreground: var(--page-foreground-color);\n\n    /* searchbar colors */\n    --searchbar-background: var(--side-nav-background);\n    --searchbar-foreground: var(--page-foreground-color);\n\n    /* searchbar size\n     * (`searchbar-width` is only applied on screens >= 768px.\n     * on smaller screens the searchbar will always fill the entire screen width) */\n    --searchbar-height: 33px;\n    --searchbar-width: 210px;\n    --searchbar-border-radius: var(--searchbar-height);\n\n    /* code block colors */\n    --code-background: #f5f5f5;\n    --code-foreground: var(--page-foreground-color);\n\n    /* fragment colors */\n    --fragment-background: #F8F9FA;\n    --fragment-foreground: #37474F;\n    --fragment-keyword: #bb6bb2;\n    --fragment-keywordtype: #8258b3;\n    --fragment-keywordflow: #d67c3b;\n    --fragment-token: #438a59;\n    --fragment-comment: #969696;\n    --fragment-link: #5383d6;\n    --fragment-preprocessor: #46aaa5;\n    --fragment-linenumber-color: #797979;\n    --fragment-linenumber-background: #f4f4f5;\n    --fragment-linenumber-border: #e3e5e7;\n    --fragment-lineheight: 20px;\n\n    /* sidebar navigation (treeview) colors */\n    --side-nav-background: #fbfbfb;\n    --side-nav-foreground: var(--page-foreground-color);\n    --side-nav-arrow-opacity: 0;\n    --side-nav-arrow-hover-opacity: 0.9;\n\n    --toc-background: var(--side-nav-background);\n    --toc-foreground: var(--side-nav-foreground);\n\n    /* height of an item in any tree / collapsible table */\n    --tree-item-height: 30px;\n\n    --memname-font-size: var(--code-font-size);\n    --memtitle-font-size: 18px;\n\n    --webkit-scrollbar-size: 7px;\n    --webkit-scrollbar-padding: 4px;\n    --webkit-scrollbar-color: var(--separator-color);\n\n    --animation-duration: .12s\n}\n\n@media screen and (max-width: 767px) {\n    html {\n        --page-font-size: 16px;\n        --navigation-font-size: 16px;\n        --toc-font-size: 15px;\n        --code-font-size: 15px; /* affects code, fragment */\n        --title-font-size: 22px;\n    }\n}\n\n@media (prefers-color-scheme: dark) {\n    html:not(.light-mode) {\n        color-scheme: dark;\n\n        --primary-color: #1982d2;\n        --primary-dark-color: #86a9c4;\n        --primary-light-color: #4779ac;\n\n        --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35);\n\n        --odd-color: rgba(100,100,100,.06);\n\n        --menu-selected-background: rgba(0,0,0,.4);\n\n        --page-background-color: #1C1D1F;\n        --page-foreground-color: #d2dbde;\n        --page-secondary-foreground-color: #859399;\n        --separator-color: #38393b;\n        --side-nav-background: #252628;\n\n        --code-background: #2a2c2f;\n\n        --tablehead-background: #2a2c2f;\n\n        --blockquote-background: #222325;\n        --blockquote-foreground: #7e8c92;\n\n        --warning-color: #3b2e04;\n        --warning-color-dark: #f1b602;\n        --warning-color-darker: #ceb670;\n        --note-color: #163750;\n        --note-color-dark: #1982D2;\n        --note-color-darker: #dcf0fa;\n        --todo-color: #2a2536;\n        --todo-color-dark: #7661b3;\n        --todo-color-darker: #ae9ed6;\n        --deprecated-color: #2e323b;\n        --deprecated-color-dark: #738396;\n        --deprecated-color-darker: #abb0bd;\n        --bug-color: #2e1917;\n        --bug-color-dark: #ad2617;\n        --bug-color-darker: #f5b1aa;\n        --invariant-color: #303a35;\n        --invariant-color-dark: #76ce96;\n        --invariant-color-darker: #cceed5;\n\n        --fragment-background: #282c34;\n        --fragment-foreground: #dbe4eb;\n        --fragment-keyword: #cc99cd;\n        --fragment-keywordtype: #ab99cd;\n        --fragment-keywordflow: #e08000;\n        --fragment-token: #7ec699;\n        --fragment-comment: #999999;\n        --fragment-link: #98c0e3;\n        --fragment-preprocessor: #65cabe;\n        --fragment-linenumber-color: #cccccc;\n        --fragment-linenumber-background: #35393c;\n        --fragment-linenumber-border: #1f1f1f;\n    }\n}\n\n/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */\nhtml.dark-mode {\n    color-scheme: dark;\n\n    --primary-color: #1982d2;\n    --primary-dark-color: #86a9c4;\n    --primary-light-color: #4779ac;\n\n    --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30);\n\n    --odd-color: rgba(100,100,100,.06);\n\n    --menu-selected-background: rgba(0,0,0,.4);\n\n    --page-background-color: #1C1D1F;\n    --page-foreground-color: #d2dbde;\n    --page-secondary-foreground-color: #859399;\n    --separator-color: #38393b;\n    --side-nav-background: #252628;\n\n    --code-background: #2a2c2f;\n\n    --tablehead-background: #2a2c2f;\n\n    --blockquote-background: #222325;\n    --blockquote-foreground: #7e8c92;\n\n    --warning-color: #3b2e04;\n    --warning-color-dark: #f1b602;\n    --warning-color-darker: #ceb670;\n    --note-color: #163750;\n    --note-color-dark: #1982D2;\n    --note-color-darker: #dcf0fa;\n    --todo-color: #2a2536;\n    --todo-color-dark: #7661b3;\n    --todo-color-darker: #ae9ed6;\n    --deprecated-color: #2e323b;\n    --deprecated-color-dark: #738396;\n    --deprecated-color-darker: #abb0bd;\n    --bug-color: #2e1917;\n    --bug-color-dark: #ad2617;\n    --bug-color-darker: #f5b1aa;\n    --invariant-color: #303a35;\n    --invariant-color-dark: #76ce96;\n    --invariant-color-darker: #cceed5;\n\n    --fragment-background: #282c34;\n    --fragment-foreground: #dbe4eb;\n    --fragment-keyword: #cc99cd;\n    --fragment-keywordtype: #ab99cd;\n    --fragment-keywordflow: #e08000;\n    --fragment-token: #7ec699;\n    --fragment-comment: #999999;\n    --fragment-link: #98c0e3;\n    --fragment-preprocessor: #65cabe;\n    --fragment-linenumber-color: #cccccc;\n    --fragment-linenumber-background: #35393c;\n    --fragment-linenumber-border: #1f1f1f;\n}\n\nbody {\n    color: var(--page-foreground-color);\n    background-color: var(--page-background-color);\n    font-size: var(--page-font-size);\n}\n\nbody, table, div, p, dl, #nav-tree .label, #nav-tree a, .title,\n.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname,\n.SelectItem, #MSearchField, .navpath li.navelem a,\n.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3,\n#page-nav ul.page-outline li a {\n    font-family: var(--font-family);\n}\n\nh1, h2, h3, h4, h5 {\n    margin-top: 1em;\n    font-weight: 600;\n    line-height: initial;\n}\n\np, div, table, dl, p.reference, p.definition {\n    font-size: var(--page-font-size);\n}\n\np.reference, p.definition {\n    color: var(--page-secondary-foreground-color);\n}\n\na:link, a:visited, a:hover, a:focus, a:active {\n    color: var(--link-color) !important;\n    font-weight: 500;\n    background: none;\n}\n\na:hover {\n    text-decoration: underline;\n}\n\na.anchor {\n    scroll-margin-top: var(--spacing-large);\n    display: block;\n}\n\n/*\n Title and top navigation\n */\n\n#top {\n    background: var(--header-background);\n    border-bottom: 1px solid var(--separator-color);\n    position: relative;\n    z-index: 99;\n}\n\n@media screen and (min-width: 768px) {\n    #top {\n        display: flex;\n        flex-wrap: wrap;\n        justify-content: space-between;\n        align-items: center;\n    }\n}\n\n#main-nav {\n    flex-grow: 5;\n    padding: var(--spacing-small) var(--spacing-medium);\n    border-bottom: 0;\n}\n\n#titlearea {\n    width: auto;\n    padding: var(--spacing-medium) var(--spacing-large);\n    background: none;\n    color: var(--header-foreground);\n    border-bottom: none;\n}\n\n@media screen and (max-width: 767px) {\n    #titlearea {\n        padding-bottom: var(--spacing-small);\n    }\n}\n\n#titlearea table tbody tr {\n    height: auto !important;\n}\n\n#projectname {\n    font-size: var(--title-font-size);\n    font-weight: 600;\n}\n\n#projectnumber {\n    font-family: inherit;\n    font-size: 60%;\n}\n\n#projectbrief {\n    font-family: inherit;\n    font-size: 80%;\n}\n\n#projectlogo {\n    vertical-align: middle;\n}\n\n#projectlogo img {\n    max-height: calc(var(--title-font-size) * 2);\n    margin-right: var(--spacing-small);\n}\n\n.sm-dox, .tabs, .tabs2, .tabs3 {\n    background: none;\n    padding: 0;\n}\n\n.tabs, .tabs2, .tabs3 {\n    border-bottom: 1px solid var(--separator-color);\n    margin-bottom: -1px;\n}\n\n.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after {\n    background: var(--page-secondary-foreground-color);\n}\n\n@media screen and (max-width: 767px) {\n    .sm-dox a span.sub-arrow {\n        background: var(--code-background);\n    }\n\n    #main-menu a.has-submenu span.sub-arrow {\n        color: var(--page-secondary-foreground-color);\n        border-radius: var(--border-radius-medium);\n    }\n\n    #main-menu a.has-submenu:hover span.sub-arrow {\n        color: var(--page-foreground-color);\n    }\n}\n\n@media screen and (min-width: 768px) {\n    .sm-dox li, .tablist li {\n        display: var(--menu-display);\n    }\n\n    .sm-dox a span.sub-arrow {\n        top: 15px;\n        right: 10px;\n        box-sizing: content-box;\n        padding: 0;\n        margin: 0;\n        display: inline-block;\n        width: 5px;\n        height: 5px;\n        transform: rotate(45deg);\n        border-width: 0;\n        border-right: 2px solid var(--header-foreground);\n        border-bottom: 2px solid var(--header-foreground);\n        background: none;\n    }\n\n    .sm-dox a:hover span.sub-arrow {\n        border-color: var(--menu-focus-foreground);\n        background: none;\n    }\n\n    .sm-dox ul a span.sub-arrow {\n        transform: rotate(-45deg);\n        border-width: 0;\n        border-right: 2px solid var(--header-foreground);\n        border-bottom: 2px solid var(--header-foreground);\n    }\n\n    .sm-dox ul a:hover span.sub-arrow {\n        border-color: var(--menu-focus-foreground);\n        background: none;\n    }\n}\n\n.sm-dox ul {\n    background: var(--page-background-color);\n    box-shadow: var(--box-shadow);\n    border: 1px solid var(--separator-color);\n    border-radius: var(--border-radius-medium) !important;\n    padding: var(--spacing-small);\n    animation: ease-out 150ms slideInMenu;\n}\n\n@keyframes slideInMenu {\n    from {\n        opacity: 0;\n        transform: translate(0px, -2px);\n    }\n\n    to {\n        opacity: 1;\n        transform: translate(0px, 0px);\n    }\n}\n\n.sm-dox ul a {\n    color: var(--page-foreground-color) !important;\n    background: none;\n    font-size: var(--navigation-font-size);\n}\n\n.sm-dox>li>ul:after {\n    border-bottom-color: var(--page-background-color) !important;\n}\n\n.sm-dox>li>ul:before {\n    border-bottom-color: var(--separator-color) !important;\n}\n\n.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus {\n    font-size: var(--navigation-font-size) !important;\n    color: var(--menu-focus-foreground) !important;\n    text-shadow: none;\n    background-color: var(--menu-focus-background);\n    border-radius: var(--border-radius-small) !important;\n}\n\n.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a {\n    text-shadow: none;\n    background: transparent;\n    background-image: none !important;\n    color: var(--header-foreground) !important;\n    font-weight: normal;\n    font-size: var(--navigation-font-size);\n    border-radius: var(--border-radius-small) !important;\n}\n\n.sm-dox a:focus {\n    outline: auto;\n}\n\n.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover {\n    text-shadow: none;\n    font-weight: normal;\n    background: var(--menu-focus-background);\n    color: var(--menu-focus-foreground) !important;\n    border-radius: var(--border-radius-small) !important;\n    font-size: var(--navigation-font-size);\n}\n\n.tablist li.current {\n    border-radius: var(--border-radius-small);\n    background: var(--menu-selected-background);\n}\n\n.tablist li {\n    margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small);\n}\n\n.tablist a {\n    padding: 0 var(--spacing-large);\n}\n\n\n/*\n Search box\n */\n\n#MSearchBox {\n    height: var(--searchbar-height);\n    background: var(--searchbar-background);\n    border-radius: var(--searchbar-border-radius);\n    border: 1px solid var(--separator-color);\n    overflow: hidden;\n    width: var(--searchbar-width);\n    position: relative;\n    box-shadow: none;\n    display: block;\n    margin-top: 0;\n    margin-right: 0;\n}\n\n@media (min-width: 768px) {\n    .sm-dox li {\n        padding: 0;\n    }\n}\n\n/* until Doxygen 1.9.4 */\n.left img#MSearchSelect {\n    left: 0;\n    user-select: none;\n    padding-left: 8px;\n}\n\n/* Doxygen 1.9.5 */\n.left span#MSearchSelect {\n    left: 0;\n    user-select: none;\n    margin-left: 8px;\n    padding: 0;\n}\n\n.left #MSearchSelect[src$=\".png\"] {\n    padding-left: 0\n}\n\n/* Doxygen 1.14.0 */\n.search-icon::before {\n    background: none;\n    top: 5px;\n}\n\n.search-icon::after {\n    background: none;\n    top: 12px;\n}\n\n.SelectionMark {\n    user-select: none;\n}\n\n.tabs .left #MSearchSelect {\n    padding-left: 0;\n}\n\n.tabs #MSearchBox {\n    position: absolute;\n    right: var(--spacing-medium);\n}\n\n@media screen and (max-width: 767px) {\n    .tabs #MSearchBox {\n        position: relative;\n        right: 0;\n        margin-left: var(--spacing-medium);\n        margin-top: 0;\n    }\n}\n\n#MSearchSelectWindow, #MSearchResultsWindow {\n    z-index: 9999;\n}\n\n#MSearchBox.MSearchBoxActive {\n    border-color: var(--primary-color);\n    box-shadow: inset 0 0 0 1px var(--primary-color);\n}\n\n#main-menu > li:last-child {\n    margin-right: 0;\n}\n\n@media screen and (max-width: 767px) {\n    #main-menu > li:last-child {\n        height: 50px;\n    }\n}\n\n#MSearchField {\n    font-size: var(--navigation-font-size);\n    height: calc(var(--searchbar-height) - 2px);\n    background: transparent;\n    width: calc(var(--searchbar-width) - 64px);\n}\n\n.MSearchBoxActive #MSearchField {\n    color: var(--searchbar-foreground);\n}\n\n#MSearchSelect {\n    top: calc(calc(var(--searchbar-height) / 2) - 11px);\n}\n\n#MSearchBox span.left, #MSearchBox span.right {\n    background: none;\n    background-image: none;\n}\n\n#MSearchBox span.right {\n    padding-top: calc(calc(var(--searchbar-height) / 2) - 12px);\n    position: absolute;\n    right: var(--spacing-small);\n}\n\n.tabs #MSearchBox span.right {\n    top: calc(calc(var(--searchbar-height) / 2) - 12px);\n}\n\n@keyframes slideInSearchResults {\n    from {\n        opacity: 0;\n        transform: translate(0, 15px);\n    }\n\n    to {\n        opacity: 1;\n        transform: translate(0, 20px);\n    }\n}\n\n#MSearchResultsWindow {\n    left: auto !important;\n    right: var(--spacing-medium);\n    border-radius: var(--border-radius-large);\n    border: 1px solid var(--separator-color);\n    transform: translate(0, 20px);\n    box-shadow: var(--box-shadow);\n    animation: ease-out 280ms slideInSearchResults;\n    background: var(--page-background-color);\n}\n\niframe#MSearchResults {\n    margin: 4px;\n}\n\niframe {\n    color-scheme: normal;\n}\n\n@media (prefers-color-scheme: dark) {\n    html:not(.light-mode) iframe#MSearchResults {\n        filter: invert() hue-rotate(180deg);\n    }\n}\n\nhtml.dark-mode iframe#MSearchResults {\n    filter: invert() hue-rotate(180deg);\n}\n\n#MSearchResults .SRPage {\n    background-color: transparent;\n}\n\n#MSearchResults .SRPage .SREntry {\n    font-size: 10pt;\n    padding: var(--spacing-small) var(--spacing-medium);\n}\n\n#MSearchSelectWindow {\n    border: 1px solid var(--separator-color);\n    border-radius: var(--border-radius-medium);\n    box-shadow: var(--box-shadow);\n    background: var(--page-background-color);\n    padding-top: var(--spacing-small);\n    padding-bottom: var(--spacing-small);\n}\n\n#MSearchSelectWindow a.SelectItem {\n    font-size: var(--navigation-font-size);\n    line-height: var(--content-line-height);\n    margin: 0 var(--spacing-small);\n    border-radius: var(--border-radius-small);\n    color: var(--page-foreground-color) !important;\n    font-weight: normal;\n}\n\n#MSearchSelectWindow a.SelectItem:hover {\n    background: var(--menu-focus-background);\n    color: var(--menu-focus-foreground) !important;\n}\n\n@media screen and (max-width: 767px) {\n    #MSearchBox {\n        margin-top: var(--spacing-medium);\n        margin-bottom: var(--spacing-medium);\n        width: calc(100vw - 30px);\n    }\n\n    #main-menu > li:last-child {\n        float: none !important;\n    }\n\n    #MSearchField {\n        width: calc(100vw - 110px);\n    }\n\n    @keyframes slideInSearchResultsMobile {\n        from {\n            opacity: 0;\n            transform: translate(0, 15px);\n        }\n\n        to {\n            opacity: 1;\n            transform: translate(0, 20px);\n        }\n    }\n\n    #MSearchResultsWindow {\n        left: var(--spacing-medium) !important;\n        right: var(--spacing-medium);\n        overflow: auto;\n        transform: translate(0, 20px);\n        animation: ease-out 280ms slideInSearchResultsMobile;\n        width: auto !important;\n    }\n\n    /*\n     * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2\n     */\n    label.main-menu-btn ~ #searchBoxPos1 {\n        top: 3px !important;\n        right: 6px !important;\n        left: 45px;\n        display: flex;\n    }\n\n    label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox {\n        margin-top: 0;\n        margin-bottom: 0;\n        flex-grow: 2;\n        float: left;\n    }\n}\n\n/*\n Tree view\n */\n\n#side-nav {\n    min-width: 8px;\n    max-width: 50vw;\n}\n\n\n#nav-tree, #top {\n    border-right: 1px solid var(--separator-color);\n}\n\n@media screen and (max-width: 767px) {\n    #side-nav {\n        display: none;\n    }\n\n    #doc-content {\n        margin-left: 0 !important;\n    }\n\n    #top {\n        border-right: none;\n    }\n}\n\n#nav-tree {\n    background: var(--side-nav-background);\n    margin-right: -1px;\n    padding: 0;\n}\n\n#nav-tree .label {\n    font-size: var(--navigation-font-size);\n    line-height: var(--tree-item-height);\n}\n\n#nav-tree span.label a:hover {\n    background: none;\n}\n\n#nav-tree .item {\n    height: var(--tree-item-height);\n    line-height: var(--tree-item-height);\n    overflow: hidden;\n    text-overflow: ellipsis;\n    margin: 0;\n    padding: 0;\n}\n\n#nav-tree-contents {\n    margin: 0;\n}\n\n#main-menu > li:last-child {\n    height: auto;\n}\n\n#nav-tree .item > a:focus {\n    outline: none;\n}\n\n#nav-sync {\n    bottom: var(--spacing-medium);\n    right: var(--spacing-medium) !important;\n    top: auto !important;\n    user-select: none;\n}\n\ndiv.nav-sync-icon {\n    border: 1px solid var(--separator-color);\n    border-radius: var(--border-radius-medium);\n    background: var(--page-background-color);\n    width: 30px;\n    height: 20px;\n}\n\ndiv.nav-sync-icon:hover {\n    background: var(--page-background-color);\n}\n\nspan.sync-icon-left, div.nav-sync-icon:hover span.sync-icon-left {\n    border-left: 2px solid var(--primary-color);\n    border-top: 2px solid var(--primary-color);\n    top: 5px;\n    left: 6px;\n}\nspan.sync-icon-right, div.nav-sync-icon:hover span.sync-icon-right {\n    border-right: 2px solid var(--primary-color);\n    border-bottom: 2px solid var(--primary-color);\n    top: 5px;\n    left: initial;\n    right: 6px;\n}\n\ndiv.nav-sync-icon.active::after, div.nav-sync-icon.active:hover::after {\n    border-top: 2px solid var(--primary-color);\n    top: 9px;\n    left: 6px;\n    width: 19px;\n}\n\n#nav-tree .selected {\n    text-shadow: none;\n    background-image: none;\n    background-color: transparent;\n    position: relative;\n    color: var(--primary-color) !important;\n    font-weight: 500;\n}\n\n#nav-tree .selected::after {\n    content: \"\";\n    position: absolute;\n    top: 1px;\n    bottom: 1px;\n    left: 0;\n    width: 4px;\n    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;\n    background: var(--primary-color);\n}\n\n\n#nav-tree a {\n    color: var(--side-nav-foreground) !important;\n    font-weight: normal;\n}\n\n#nav-tree a:focus {\n    outline-style: auto;\n}\n\n#nav-tree .arrow {\n    opacity: var(--side-nav-arrow-opacity);\n    background: none;\n}\n\n#nav-tree span.arrowhead {\n    margin: 0 0 1px 2px;\n}\n\nspan.arrowhead {\n    border-color: var(--primary-light-color);\n}\n\n.selected span.arrowhead {\n    border-color: var(--primary-color);\n}\n\n#nav-tree-contents > ul > li:first-child > div > a {\n    opacity: 0;\n    pointer-events: none;\n}\n\n.contents .arrow {\n    color: inherit;\n    cursor: pointer;\n    font-size: 45%;\n    vertical-align: middle;\n    margin-right: 2px;\n    font-family: serif;\n    height: auto;\n    padding-bottom: 4px;\n}\n\n#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow {\n    opacity: var(--side-nav-arrow-hover-opacity);\n}\n\n#nav-tree .selected a {\n    color: var(--primary-color) !important;\n    font-weight: bolder;\n    font-weight: 600;\n}\n\n.ui-resizable-e {\n    background: none;\n}\n\n.ui-resizable-e:hover {\n    background: var(--separator-color);\n}\n\n/*\n Contents\n */\n\ndiv.header {\n    border-bottom: 1px solid var(--separator-color);\n    background: none;\n    background-image: none;\n}\n\n@media screen and (min-width: 1000px) {\n    #doc-content > div > div.contents,\n    .PageDoc > div.contents {\n        display: flex;\n        flex-direction: row-reverse;\n        flex-wrap: nowrap;\n        align-items: flex-start;\n    }\n\n    div.contents .textblock {\n        min-width: 200px;\n        flex-grow: 1;\n    }\n}\n\ndiv.contents, div.header .title, div.header .summary {\n    max-width: var(--content-maxwidth);\n}\n\ndiv.contents, div.header .title  {\n    line-height: initial;\n    margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto;\n}\n\ndiv.header .summary {\n    margin: var(--spacing-medium) auto 0 auto;\n}\n\ndiv.headertitle {\n    padding: 0;\n}\n\ndiv.header .title {\n    font-weight: 600;\n    font-size: 225%;\n    padding: var(--spacing-medium) var(--spacing-xlarge);\n    word-break: break-word;\n}\n\ndiv.header .summary {\n    width: auto;\n    display: block;\n    float: none;\n    padding: 0 var(--spacing-large);\n}\n\ntd.memSeparator {\n    border-color: var(--separator-color);\n}\n\nspan.mlabel {\n    background: var(--primary-color);\n    color: var(--on-primary-color);\n    border: none;\n    padding: 4px 9px;\n    border-radius: var(--border-radius-large);\n    margin-right: var(--spacing-medium);\n}\n\nspan.mlabel:last-of-type {\n    margin-right: 2px;\n}\n\ndiv.contents {\n    padding: 0 var(--spacing-xlarge);\n}\n\ndiv.contents p, div.contents li {\n    line-height: var(--content-line-height);\n}\n\ndiv.contents div.dyncontent {\n    margin: var(--spacing-medium) 0;\n}\n\n@media screen and (max-width: 767px) {\n    div.contents {\n        padding: 0 var(--spacing-large);\n    }\n\n    div.header .title {\n        padding: var(--spacing-medium) var(--spacing-large);\n    }\n}\n\n@media (prefers-color-scheme: dark) {\n    html:not(.light-mode) div.contents div.dyncontent img,\n    html:not(.light-mode) div.contents center img,\n    html:not(.light-mode) div.contents > table img,\n    html:not(.light-mode) div.contents div.dyncontent iframe,\n    html:not(.light-mode) div.contents center iframe,\n    html:not(.light-mode) div.contents table iframe,\n    html:not(.light-mode) div.contents .dotgraph iframe {\n        filter: brightness(89%) hue-rotate(180deg) invert();\n    }\n}\n\nhtml.dark-mode div.contents div.dyncontent img,\nhtml.dark-mode div.contents center img,\nhtml.dark-mode div.contents > table img,\nhtml.dark-mode div.contents div.dyncontent iframe,\nhtml.dark-mode div.contents center iframe,\nhtml.dark-mode div.contents table iframe,\nhtml.dark-mode div.contents .dotgraph iframe\n {\n    filter: brightness(89%) hue-rotate(180deg) invert();\n}\n\ntd h2.groupheader, h2.groupheader {\n    border-bottom: 0px;\n    color: var(--page-foreground-color);\n    box-shadow:\n        100px 0 var(--page-background-color),\n        -100px 0 var(--page-background-color),\n        100px 0.75px var(--separator-color),\n        -100px 0.75px var(--separator-color),\n        500px 0 var(--page-background-color),\n        -500px 0 var(--page-background-color),\n        500px 0.75px var(--separator-color),\n        -500px 0.75px var(--separator-color),\n        900px 0 var(--page-background-color),\n        -900px 0 var(--page-background-color),\n        900px 0.75px var(--separator-color),\n        -900px 0.75px var(--separator-color),\n        1400px 0 var(--page-background-color),\n        -1400px 0 var(--page-background-color),\n        1400px 0.75px var(--separator-color),\n        -1400px 0.75px var(--separator-color),\n        1900px 0 var(--page-background-color),\n        -1900px 0 var(--page-background-color),\n        1900px 0.75px var(--separator-color),\n        -1900px 0.75px var(--separator-color);\n}\n\nblockquote {\n    margin: 0 var(--spacing-medium) 0 var(--spacing-medium);\n    padding: var(--spacing-small) var(--spacing-large);\n    background: var(--blockquote-background);\n    color: var(--blockquote-foreground);\n    border-left: 0;\n    overflow: visible;\n    border-radius: var(--border-radius-medium);\n    overflow: visible;\n    position: relative;\n}\n\nblockquote::before, blockquote::after {\n    font-weight: bold;\n    font-family: serif;\n    font-size: 360%;\n    opacity: .15;\n    position: absolute;\n}\n\nblockquote::before {\n    content: \"“\";\n    left: -10px;\n    top: 4px;\n}\n\nblockquote::after {\n    content: \"”\";\n    right: -8px;\n    bottom: -25px;\n}\n\nblockquote p {\n    margin: var(--spacing-small) 0 var(--spacing-medium) 0;\n}\n.paramname, .paramname em {\n    font-weight: 600;\n    color: var(--primary-dark-color);\n}\n\n.paramname > code {\n    border: 0;\n}\n\ntable.params .paramname {\n    font-weight: 600;\n    font-family: var(--font-family-monospace);\n    font-size: var(--code-font-size);\n    padding-right: var(--spacing-small);\n    line-height: var(--table-line-height);\n}\n\nh1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {\n    text-shadow: 0 0 15px var(--primary-light-color);\n}\n\n.alphachar a {\n    color: var(--page-foreground-color);\n}\n\n.dotgraph {\n    max-width: 100%;\n    overflow-x: scroll;\n}\n\n.dotgraph .caption {\n    position: sticky;\n    left: 0;\n}\n\n/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */\n.interactive_dotgraph .dotgraph iframe {\n    max-width: 100%;\n}\n\n/*\n Table of Contents\n */\n\ndiv.contents .toc {\n    max-height: var(--toc-max-height);\n    min-width: var(--toc-width);\n    border: 0;\n    border-left: 1px solid var(--separator-color);\n    border-radius: 0;\n    background-color: var(--page-background-color);\n    box-shadow: none;\n    position: sticky;\n    top: var(--toc-sticky-top);\n    padding: 0 var(--spacing-large);\n    margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large);\n}\n\ndiv.toc h3 {\n    color: var(--toc-foreground);\n    font-size: var(--navigation-font-size);\n    margin: var(--spacing-large) 0 var(--spacing-medium) 0;\n}\n\ndiv.toc li {\n    padding: 0;\n    background: none;\n    line-height: var(--toc-font-size);\n    margin: var(--toc-font-size) 0 0 0;\n}\n\ndiv.toc li::before {\n    display: none;\n}\n\ndiv.toc ul {\n    margin-top: 0\n}\n\ndiv.toc li a {\n    font-size: var(--toc-font-size);\n    color: var(--page-foreground-color) !important;\n    text-decoration: none;\n}\n\ndiv.toc li a:hover, div.toc li a.active {\n    color: var(--primary-color) !important;\n}\n\ndiv.toc li a.aboveActive {\n    color: var(--page-secondary-foreground-color) !important;\n}\n\n\n@media screen and (max-width: 999px) {\n    div.contents .toc {\n        max-height: 45vh;\n        float: none;\n        width: auto;\n        margin: 0 0 var(--spacing-medium) 0;\n        position: relative;\n        top: 0;\n        position: relative;\n        border: 1px solid var(--separator-color);\n        border-radius: var(--border-radius-medium);\n        background-color: var(--toc-background);\n        box-shadow: var(--box-shadow);\n    }\n\n    div.contents .toc.interactive {\n        max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large));\n        overflow: hidden;\n    }\n\n    div.contents .toc > h3 {\n        -webkit-tap-highlight-color: transparent;\n        cursor: pointer;\n        position: sticky;\n        top: 0;\n        background-color: var(--toc-background);\n        margin: 0;\n        padding: var(--spacing-large) 0;\n        display: block;\n    }\n\n    div.contents .toc.interactive > h3::before {\n        content: \"\";\n        width: 0;\n        height: 0;\n        border-left: 4px solid transparent;\n        border-right: 4px solid transparent;\n        border-top: 5px solid var(--primary-color);\n        display: inline-block;\n        margin-right: var(--spacing-small);\n        margin-bottom: calc(var(--navigation-font-size) / 4);\n        transform: rotate(-90deg);\n        transition: transform var(--animation-duration) ease-out;\n    }\n\n    div.contents .toc.interactive.open > h3::before {\n        transform: rotate(0deg);\n    }\n\n    div.contents .toc.interactive.open {\n        max-height: 45vh;\n        overflow: auto;\n        transition: max-height 0.2s ease-in-out;\n    }\n\n    div.contents .toc a, div.contents .toc a.active {\n        color: var(--primary-color) !important;\n    }\n\n    div.contents .toc a:hover {\n        text-decoration: underline;\n    }\n}\n\n/*\n Page Outline (Doxygen >= 1.14.0)\n*/\n\n#page-nav {\n    background: var(--page-background-color);\n    border-left: 1px solid var(--separator-color);\n}\n\n#page-nav #page-nav-resize-handle {\n    background: var(--separator-color);\n}\n\n#page-nav #page-nav-resize-handle::after {\n    border-left: 1px solid var(--primary-color);\n    border-right: 1px solid var(--primary-color);\n}\n\n#page-nav #page-nav-tree #page-nav-contents {\n    top: var(--spacing-large);\n}\n\n#page-nav ul.page-outline {\n    margin: 0;\n    padding: 0;\n}\n\n#page-nav ul.page-outline li a {\n    font-size: var(--toc-font-size) !important;\n    color: var(--page-secondary-foreground-color) !important;\n    display: inline-block;\n    line-height: calc(2 * var(--toc-font-size));\n}\n\n#page-nav ul.page-outline li a a.anchorlink {\n    display: none;\n}\n\n#page-nav ul.page-outline li.vis ~ * a {\n    color: var(--page-foreground-color) !important;\n}\n\n#page-nav ul.page-outline li.vis:not(.vis ~ .vis) a, #page-nav ul.page-outline li a:hover {\n    color: var(--primary-color) !important;\n}\n\n#page-nav ul.page-outline .vis {\n    background: var(--page-background-color);\n    position: relative;\n}\n\n#page-nav ul.page-outline .vis::after {\n    content: \"\";\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    width: 4px;\n    background: var(--page-secondary-foreground-color);\n}\n\n#page-nav ul.page-outline .vis:not(.vis ~ .vis)::after {\n    top: 1px;\n    border-top-right-radius: var(--border-radius-small);\n}\n\n#page-nav ul.page-outline .vis:not(:has(~ .vis))::after {\n    bottom: 1px;\n    border-bottom-right-radius: var(--border-radius-small);\n}\n\n\n#page-nav ul.page-outline .arrow {\n    display: inline-block;\n}\n\n#page-nav ul.page-outline .arrow span {\n    display: none;\n}\n\n@media screen and (max-width: 767px) {\n    #container {\n        grid-template-columns: initial !important;\n    }\n\n    #page-nav {\n        display: none;\n    }\n}\n\n/*\n Code & Fragments\n */\n\ncode, div.fragment, pre.fragment, span.tt {\n    border: 1px solid var(--separator-color);\n    overflow: hidden;\n}\n\ncode, span.tt {\n    display: inline;\n    background: var(--code-background);\n    color: var(--code-foreground);\n    padding: 2px 6px;\n    border-radius: var(--border-radius-small);\n}\n\ndiv.fragment, pre.fragment {\n    border-radius: var(--border-radius-medium);\n    margin: var(--spacing-medium) 0;\n    padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large);\n    background: var(--fragment-background);\n    color: var(--fragment-foreground);\n    overflow-x: auto;\n}\n\n@media screen and (max-width: 767px) {\n    div.fragment, pre.fragment {\n        border-top-right-radius: 0;\n        border-bottom-right-radius: 0;\n        border-right: 0;\n    }\n\n    .contents > div.fragment,\n    .textblock > div.fragment,\n    .textblock > pre.fragment,\n    .textblock > .tabbed > ul > li > div.fragment,\n    .textblock > .tabbed > ul > li > pre.fragment,\n    .contents > .doxygen-awesome-fragment-wrapper > div.fragment,\n    .textblock > .doxygen-awesome-fragment-wrapper > div.fragment,\n    .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment,\n    .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > div.fragment,\n    .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > pre.fragment {\n        margin: var(--spacing-medium) calc(0px - var(--spacing-large));\n        border-radius: 0;\n        border-left: 0;\n    }\n\n    .textblock li > .fragment,\n    .textblock li > .doxygen-awesome-fragment-wrapper > .fragment {\n        margin: var(--spacing-medium) calc(0px - var(--spacing-large));\n    }\n\n    .memdoc li > .fragment,\n    .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment {\n        margin: var(--spacing-medium) calc(0px - var(--spacing-medium));\n    }\n\n    .textblock ul, .memdoc ul {\n        overflow: initial;\n    }\n\n    .memdoc > div.fragment,\n    .memdoc > pre.fragment,\n    dl dd > div.fragment,\n    dl dd pre.fragment,\n    .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment,\n    .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment,\n    dl dd > .doxygen-awesome-fragment-wrapper > div.fragment,\n    dl dd .doxygen-awesome-fragment-wrapper > pre.fragment {\n        margin: var(--spacing-medium) calc(0px - var(--spacing-medium));\n        border-radius: 0;\n        border-left: 0;\n    }\n}\n\ncode, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span, span.tt {\n    font-family: var(--font-family-monospace);\n    font-size: var(--code-font-size) !important;\n}\n\ndiv.line:after {\n    margin-right: var(--spacing-medium);\n}\n\ndiv.fragment .line, pre.fragment {\n    white-space: pre;\n    word-wrap: initial;\n    line-height: var(--fragment-lineheight);\n}\n\ndiv.fragment span.keyword {\n    color: var(--fragment-keyword);\n}\n\ndiv.fragment span.keywordtype {\n    color: var(--fragment-keywordtype);\n}\n\ndiv.fragment span.keywordflow {\n    color: var(--fragment-keywordflow);\n}\n\ndiv.fragment span.stringliteral {\n    color: var(--fragment-token)\n}\n\ndiv.fragment span.comment {\n    color: var(--fragment-comment);\n}\n\ndiv.fragment a.code {\n    color: var(--fragment-link) !important;\n}\n\ndiv.fragment span.preprocessor {\n    color: var(--fragment-preprocessor);\n}\n\ndiv.fragment span.lineno {\n    display: inline-block;\n    width: 27px;\n    border-right: none;\n    background: var(--fragment-linenumber-background);\n    color: var(--fragment-linenumber-color);\n}\n\ndiv.fragment span.lineno a {\n    background: none;\n    color: var(--fragment-link) !important;\n}\n\ndiv.fragment > .line:first-child .lineno {\n    box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border);\n    background-color: var(--fragment-linenumber-background) !important;\n}\n\ndiv.line {\n    border-radius: var(--border-radius-small);\n}\n\ndiv.line.glow {\n    background-color: var(--primary-light-color);\n    box-shadow: none;\n}\n\n/*\n dl warning, attention, note, deprecated, bug, ...\n */\n\ndl {\n    line-height: calc(1.65 * var(--page-font-size));\n}\n\ndl.bug dt a, dl.deprecated dt a, dl.todo dt a {\n    font-weight: bold !important;\n}\n\ndl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.post, dl.todo, dl.remark {\n    padding: var(--spacing-medium);\n    margin: var(--spacing-medium) 0;\n    color: var(--page-background-color);\n    overflow: hidden;\n    margin-left: 0;\n    border-radius: var(--border-radius-small);\n}\n\ndl.section dd {\n    margin-bottom: 2px;\n}\n\ndl.warning, dl.attention {\n    background: var(--warning-color);\n    border-left: 8px solid var(--warning-color-dark);\n    color: var(--warning-color-darker);\n}\n\ndl.warning dt, dl.attention dt {\n    color: var(--warning-color-dark);\n}\n\ndl.note, dl.remark {\n    background: var(--note-color);\n    border-left: 8px solid var(--note-color-dark);\n    color: var(--note-color-darker);\n}\n\ndl.note dt, dl.remark dt {\n    color: var(--note-color-dark);\n}\n\ndl.todo {\n    background: var(--todo-color);\n    border-left: 8px solid var(--todo-color-dark);\n    color: var(--todo-color-darker);\n}\n\ndl.todo dt a {\n    color: var(--todo-color-dark) !important;\n}\n\ndl.bug dt a {\n    color: var(--todo-color-dark) !important;\n}\n\ndl.bug {\n    background: var(--bug-color);\n    border-left: 8px solid var(--bug-color-dark);\n    color: var(--bug-color-darker);\n}\n\ndl.bug dt a {\n    color: var(--bug-color-dark) !important;\n}\n\ndl.deprecated {\n    background: var(--deprecated-color);\n    border-left: 8px solid var(--deprecated-color-dark);\n    color: var(--deprecated-color-darker);\n}\n\ndl.deprecated dt a {\n    color: var(--deprecated-color-dark) !important;\n}\n\ndl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd {\n    margin-inline-start: 0px;\n}\n\ndl.invariant, dl.pre, dl.post {\n    background: var(--invariant-color);\n    border-left: 8px solid var(--invariant-color-dark);\n    color: var(--invariant-color-darker);\n}\n\ndl.invariant dt, dl.pre dt, dl.post dt {\n    color: var(--invariant-color-dark);\n}\n\n/*\n memitem\n */\n\ndiv.memdoc, div.memproto, h2.memtitle {\n    box-shadow: none;\n    background-image: none;\n    border: none;\n}\n\ndiv.memdoc {\n    padding: 0 var(--spacing-medium);\n    background: var(--page-background-color);\n}\n\nh2.memtitle, div.memitem {\n    border: 1px solid var(--separator-color);\n    box-shadow: var(--box-shadow);\n}\n\nh2.memtitle {\n    box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow);\n}\n\ndiv.memitem {\n    transition: none;\n}\n\ndiv.memproto, h2.memtitle {\n    background: var(--fragment-background);\n}\n\nh2.memtitle {\n    font-weight: 500;\n    font-size: var(--memtitle-font-size);\n    font-family: var(--font-family-monospace);\n    border-bottom: none;\n    border-top-left-radius: var(--border-radius-medium);\n    border-top-right-radius: var(--border-radius-medium);\n    word-break: break-all;\n    position: relative;\n}\n\nh2.memtitle:after {\n    content: \"\";\n    display: block;\n    background: var(--fragment-background);\n    height: var(--spacing-medium);\n    bottom: calc(0px - var(--spacing-medium));\n    left: 0;\n    right: -14px;\n    position: absolute;\n    border-top-right-radius: var(--border-radius-medium);\n}\n\nh2.memtitle > span.permalink {\n    font-size: inherit;\n}\n\nh2.memtitle > span.permalink > a {\n    text-decoration: none;\n    padding-left: 3px;\n    margin-right: -4px;\n    user-select: none;\n    display: inline-block;\n    margin-top: -6px;\n}\n\nh2.memtitle > span.permalink > a:hover {\n    color: var(--primary-dark-color) !important;\n}\n\na:target + h2.memtitle, a:target + h2.memtitle + div.memitem {\n    border-color: var(--primary-light-color);\n}\n\ndiv.memitem {\n    border-top-right-radius: var(--border-radius-medium);\n    border-bottom-right-radius: var(--border-radius-medium);\n    border-bottom-left-radius: var(--border-radius-medium);\n    border-top-left-radius: 0;\n    overflow: hidden;\n    display: block !important;\n}\n\ndiv.memdoc {\n    border-radius: 0;\n}\n\ndiv.memproto {\n    border-radius: 0 var(--border-radius-small) 0 0;\n    overflow: auto;\n    border-bottom: 1px solid var(--separator-color);\n    padding: var(--spacing-medium);\n    margin-bottom: -1px;\n}\n\ndiv.memtitle {\n    border-top-right-radius: var(--border-radius-medium);\n    border-top-left-radius: var(--border-radius-medium);\n}\n\ndiv.memproto table.memname {\n    font-family: var(--font-family-monospace);\n    color: var(--page-foreground-color);\n    font-size: var(--memname-font-size);\n    text-shadow: none;\n}\n\ndiv.memproto div.memtemplate {\n    font-family: var(--font-family-monospace);\n    color: var(--primary-dark-color);\n    font-size: var(--memname-font-size);\n    margin-left: 2px;\n    text-shadow: none;\n}\n\ntable.mlabels, table.mlabels > tbody {\n    display: block;\n}\n\ntd.mlabels-left {\n    width: auto;\n}\n\ntd.mlabels-right {\n    margin-top: 3px;\n    position: sticky;\n    left: 0;\n}\n\ntable.mlabels > tbody > tr:first-child {\n    display: flex;\n    justify-content: space-between;\n    flex-wrap: wrap;\n}\n\n.memname, .memitem span.mlabels {\n    margin: 0\n}\n\n/*\n reflist\n */\n\ndl.reflist {\n    box-shadow: var(--box-shadow);\n    border-radius: var(--border-radius-medium);\n    border: 1px solid var(--separator-color);\n    overflow: hidden;\n    padding: 0;\n}\n\n\ndl.reflist dt, dl.reflist dd {\n    box-shadow: none;\n    text-shadow: none;\n    background-image: none;\n    border: none;\n    padding: 12px;\n}\n\n\ndl.reflist dt {\n    font-weight: 500;\n    border-radius: 0;\n    background: var(--code-background);\n    border-bottom: 1px solid var(--separator-color);\n    color: var(--page-foreground-color)\n}\n\n\ndl.reflist dd {\n    background: none;\n}\n\n/*\n Table\n */\n\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname),\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody {\n    display: inline-block;\n    max-width: 100%;\n}\n\n.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) {\n    margin-left: calc(0px - var(--spacing-large));\n    margin-right: calc(0px - var(--spacing-large));\n    max-width: calc(100% + 2 * var(--spacing-large));\n}\n\ntable.fieldtable,\ntable.markdownTable tbody,\ntable.doxtable tbody {\n    border: none;\n    margin: var(--spacing-medium) 0;\n    box-shadow: 0 0 0 1px var(--separator-color);\n    border-radius: var(--border-radius-small);\n}\n\ntable.markdownTable, table.doxtable, table.fieldtable {\n    padding: 1px;\n}\n\ntable.doxtable caption {\n    display: block;\n}\n\ntable.fieldtable {\n    border-collapse: collapse;\n    width: 100%;\n}\n\nth.markdownTableHeadLeft,\nth.markdownTableHeadRight,\nth.markdownTableHeadCenter,\nth.markdownTableHeadNone,\ntable.doxtable th {\n    background: var(--tablehead-background);\n    color: var(--tablehead-foreground);\n    font-weight: 600;\n    font-size: var(--page-font-size);\n}\n\nth.markdownTableHeadLeft:first-child,\nth.markdownTableHeadRight:first-child,\nth.markdownTableHeadCenter:first-child,\nth.markdownTableHeadNone:first-child,\ntable.doxtable tr th:first-child {\n    border-top-left-radius: var(--border-radius-small);\n}\n\nth.markdownTableHeadLeft:last-child,\nth.markdownTableHeadRight:last-child,\nth.markdownTableHeadCenter:last-child,\nth.markdownTableHeadNone:last-child,\ntable.doxtable tr th:last-child {\n    border-top-right-radius: var(--border-radius-small);\n}\n\ntable.markdownTable td,\ntable.markdownTable th,\ntable.fieldtable td,\ntable.fieldtable th,\ntable.doxtable td,\ntable.doxtable th {\n    border: 1px solid var(--separator-color);\n    padding: var(--spacing-small) var(--spacing-medium);\n}\n\ntable.markdownTable td:last-child,\ntable.markdownTable th:last-child,\ntable.fieldtable td:last-child,\ntable.fieldtable th:last-child,\ntable.doxtable td:last-child,\ntable.doxtable th:last-child {\n    border-right: none;\n}\n\ntable.markdownTable td:first-child,\ntable.markdownTable th:first-child,\ntable.fieldtable td:first-child,\ntable.fieldtable th:first-child,\ntable.doxtable td:first-child,\ntable.doxtable th:first-child {\n    border-left: none;\n}\n\ntable.markdownTable tr:first-child td,\ntable.markdownTable tr:first-child th,\ntable.fieldtable tr:first-child td,\ntable.fieldtable tr:first-child th,\ntable.doxtable tr:first-child td,\ntable.doxtable tr:first-child th {\n    border-top: none;\n}\n\ntable.markdownTable tr:last-child td,\ntable.markdownTable tr:last-child th,\ntable.fieldtable tr:last-child td,\ntable.fieldtable tr:last-child th,\ntable.doxtable tr:last-child td,\ntable.doxtable tr:last-child th {\n    border-bottom: none;\n}\n\ntable.markdownTable tr, table.doxtable tr {\n    border-bottom: 1px solid var(--separator-color);\n}\n\ntable.markdownTable tr:last-child, table.doxtable tr:last-child {\n    border-bottom: none;\n}\n\n.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) {\n    display: block;\n}\n\n.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody {\n    display: table;\n    width: 100%;\n}\n\ntable.fieldtable th {\n    font-size: var(--page-font-size);\n    font-weight: 600;\n    background-image: none;\n    background-color: var(--tablehead-background);\n    color: var(--tablehead-foreground);\n}\n\ntable.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit, .fieldtable td.fielddoc, .fieldtable th {\n    border-bottom: 1px solid var(--separator-color);\n    border-right: 1px solid var(--separator-color);\n}\n\ntable.fieldtable tr:last-child td:first-child {\n    border-bottom-left-radius: var(--border-radius-small);\n}\n\ntable.fieldtable tr:last-child td:last-child {\n    border-bottom-right-radius: var(--border-radius-small);\n}\n\n.memberdecls td.glow, .fieldtable tr.glow {\n    background-color: var(--primary-light-color);\n    box-shadow: none;\n}\n\ntable.memberdecls {\n    display: block;\n    -webkit-tap-highlight-color: transparent;\n}\n\ntable.memberdecls tr[class^='memitem'] {\n    font-family: var(--font-family-monospace);\n    font-size: var(--code-font-size);\n}\n\ntable.memberdecls tr[class^='memitem'] .memTemplParams {\n    font-family: var(--font-family-monospace);\n    font-size: var(--code-font-size);\n    color: var(--primary-dark-color);\n    white-space: normal;\n}\n\ntable.memberdecls tr.heading + tr[class^='memitem'] td.memItemLeft,\ntable.memberdecls tr.heading + tr[class^='memitem'] td.memItemRight,\ntable.memberdecls td.memItemLeft,\ntable.memberdecls td.memItemRight,\ntable.memberdecls .memTemplItemLeft,\ntable.memberdecls .memTemplItemRight,\ntable.memberdecls .memTemplParams {\n    transition: none;\n    padding-top: var(--spacing-small);\n    padding-bottom: var(--spacing-small);\n    border-top: 1px solid var(--separator-color);\n    border-bottom: 1px solid var(--separator-color);\n    background-color: var(--fragment-background);\n}\n\n@media screen and (min-width: 768px) {\n\n    tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {\n        border-top-right-radius: var(--border-radius-small);\n    }\n\n    table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight {\n        border-bottom-right-radius: var(--border-radius-small);\n    }\n\n    table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft {\n        border-bottom-left-radius: var(--border-radius-small);\n    }\n\n    tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft {\n        border-top-left-radius: var(--border-radius-small);\n    }\n\n}\n\ntable.memname td.memname {\n    font-size: var(--memname-font-size);\n}\n\ntable.memberdecls .memTemplItemLeft,\ntable.memberdecls .template .memItemLeft,\ntable.memberdecls .memTemplItemRight,\ntable.memberdecls .template .memItemRight {\n    padding-top: 2px;\n}\n\ntable.memberdecls .memTemplParams {\n    border-bottom: 0;\n    border-left: 1px solid var(--separator-color);\n    border-right: 1px solid var(--separator-color);\n    border-radius: var(--border-radius-small) var(--border-radius-small) 0 0;\n    padding-bottom: var(--spacing-small);\n}\n\ntable.memberdecls .memTemplItemLeft, table.memberdecls .template .memItemLeft {\n    border-radius: 0 0 0 var(--border-radius-small);\n    border-left: 1px solid var(--separator-color);\n    border-top: 0;\n}\n\ntable.memberdecls .memTemplItemRight, table.memberdecls .template .memItemRight {\n    border-radius: 0 0 var(--border-radius-small) 0;\n    border-right: 1px solid var(--separator-color);\n    padding-left: 0;\n    border-top: 0;\n}\n\ntable.memberdecls .memItemLeft {\n    border-radius: var(--border-radius-small) 0 0 var(--border-radius-small);\n    border-left: 1px solid var(--separator-color);\n    padding-left: var(--spacing-medium);\n    padding-right: 0;\n}\n\ntable.memberdecls .memItemRight  {\n    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;\n    border-right: 1px solid var(--separator-color);\n    padding-right: var(--spacing-medium);\n    padding-left: 0;\n\n}\n\ntable.memberdecls .mdescLeft, table.memberdecls .mdescRight {\n    background: none;\n    color: var(--page-foreground-color);\n    padding: var(--spacing-small) 0;\n    border: 0;\n}\n\ntable.memberdecls [class^=\"memdesc\"] {\n    box-shadow: none;\n}\n\n\ntable.memberdecls .memItemLeft,\ntable.memberdecls .memTemplItemLeft {\n    padding-right: var(--spacing-medium);\n}\n\ntable.memberdecls .memSeparator {\n    background: var(--page-background-color);\n    height: var(--spacing-large);\n    border: 0;\n    transition: none;\n}\n\ntable.memberdecls .groupheader {\n    margin-bottom: var(--spacing-large);\n}\n\ntable.memberdecls .inherit_header td {\n    padding: 0 0 var(--spacing-medium) 0;\n    text-indent: -12px;\n    color: var(--page-secondary-foreground-color);\n}\n\ntable.memberdecls span.dynarrow {\n    left: 10px;\n}\n\ntable.memberdecls img[src=\"closed.png\"],\ntable.memberdecls img[src=\"open.png\"],\ndiv.dynheader img[src=\"open.png\"],\ndiv.dynheader img[src=\"closed.png\"] {\n    width: 0;\n    height: 0;\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n    border-top: 5px solid var(--primary-color);\n    margin-top: 8px;\n    display: block;\n    float: left;\n    margin-left: -10px;\n    transition: transform var(--animation-duration) ease-out;\n}\n\ntr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft, tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {\n    border-top: 1px solid var(--separator-color);\n}\n\ntable.memberdecls img {\n    margin-right: 10px;\n}\n\ntable.memberdecls img[src=\"closed.png\"],\ndiv.dynheader img[src=\"closed.png\"] {\n    transform: rotate(-90deg);\n\n}\n\n.compoundTemplParams {\n    font-family: var(--font-family-monospace);\n    color: var(--primary-dark-color);\n    font-size: var(--code-font-size);\n}\n\n@media screen and (max-width: 767px) {\n\n    table.memberdecls .memItemLeft,\n    table.memberdecls .memItemRight,\n    table.memberdecls .mdescLeft,\n    table.memberdecls .mdescRight,\n    table.memberdecls .memTemplItemLeft,\n    table.memberdecls .memTemplItemRight,\n    table.memberdecls .memTemplParams,\n    table.memberdecls .template .memItemLeft,\n    table.memberdecls .template .memItemRight,\n    table.memberdecls .template .memParams {\n        display: block;\n        text-align: left;\n        padding-left: var(--spacing-large);\n        margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large));\n        border-right: none;\n        border-left: none;\n        border-radius: 0;\n        white-space: normal;\n    }\n\n    table.memberdecls .memItemLeft,\n    table.memberdecls .mdescLeft,\n    table.memberdecls .memTemplItemLeft,\n    table.memberdecls .template .memItemLeft {\n        border-bottom: 0 !important;\n        padding-bottom: 0 !important;\n    }\n\n    table.memberdecls .memTemplItemLeft,\n    table.memberdecls .template .memItemLeft {\n        padding-top: 0;\n    }\n\n    table.memberdecls .mdescLeft {\n        margin-bottom: calc(0px - var(--page-font-size));\n    }\n\n    table.memberdecls .memItemRight,\n    table.memberdecls .mdescRight,\n    table.memberdecls .memTemplItemRight,\n    table.memberdecls .template .memItemRight {\n        border-top: 0 !important;\n        padding-top: 0 !important;\n        padding-right: var(--spacing-large);\n        padding-bottom: var(--spacing-medium);\n        overflow-x: auto;\n    }\n\n    table.memberdecls tr[class^='memitem']:not(.inherit) {\n        display: block;\n        width: calc(100vw - 2 * var(--spacing-large));\n    }\n\n    table.memberdecls .mdescRight {\n        color: var(--page-foreground-color);\n    }\n\n    table.memberdecls tr.inherit {\n        visibility: hidden;\n    }\n\n    table.memberdecls tr[style=\"display: table-row;\"] {\n        display: block !important;\n        visibility: visible;\n        width: calc(100vw - 2 * var(--spacing-large));\n        animation: fade .5s;\n    }\n\n    @keyframes fade {\n        0% {\n            opacity: 0;\n            max-height: 0;\n        }\n\n        100% {\n            opacity: 1;\n            max-height: 200px;\n        }\n    }\n\n    tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight {\n        border-top-right-radius: 0;\n    }\n\n    table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight {\n        border-bottom-right-radius: 0;\n    }\n\n    table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft {\n        border-bottom-left-radius: 0;\n    }\n\n    tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft {\n        border-top-left-radius: 0;\n    }\n}\n\n\n/*\n Horizontal Rule\n */\n\nhr {\n    margin-top: var(--spacing-large);\n    margin-bottom: var(--spacing-large);\n    height: 1px;\n    background-color: var(--separator-color);\n    border: 0;\n}\n\n.contents hr {\n    box-shadow: 100px 0 var(--separator-color),\n                -100px 0 var(--separator-color),\n                500px 0 var(--separator-color),\n                -500px 0 var(--separator-color),\n                900px 0 var(--separator-color),\n                -900px 0 var(--separator-color),\n                1400px 0 var(--separator-color),\n                -1400px 0 var(--separator-color),\n                1900px 0 var(--separator-color),\n                -1900px 0 var(--separator-color);\n}\n\n.contents img, .contents .center, .contents center, .contents div.image object {\n    max-width: 100%;\n    overflow: auto;\n}\n\n@media screen and (max-width: 767px) {\n    .contents .dyncontent > .center, .contents > center {\n        margin-left: calc(0px - var(--spacing-large));\n        margin-right: calc(0px - var(--spacing-large));\n        max-width: calc(100% + 2 * var(--spacing-large));\n    }\n}\n\n/*\n Directories\n */\ndiv.directory {\n    border-top: 1px solid var(--separator-color);\n    border-bottom: 1px solid var(--separator-color);\n    width: auto;\n}\n\ntable.directory {\n    font-family: var(--font-family);\n    font-size: var(--page-font-size);\n    font-weight: normal;\n    width: 100%;\n}\n\ntable.directory td.entry, table.directory td.desc {\n    padding: calc(var(--spacing-small) / 2) var(--spacing-small);\n    line-height: var(--table-line-height);\n}\n\ntable.directory tr.even td:last-child {\n    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;\n}\n\ntable.directory tr.even td:first-child {\n    border-radius: var(--border-radius-small) 0 0 var(--border-radius-small);\n}\n\ntable.directory tr.even:last-child td:last-child {\n    border-radius: 0 var(--border-radius-small) 0 0;\n}\n\ntable.directory tr.even:last-child td:first-child {\n    border-radius: var(--border-radius-small) 0 0 0;\n}\n\ntable.directory td.desc {\n    min-width: 250px;\n}\n\ntable.directory tr.even {\n    background-color: var(--odd-color);\n}\n\ntable.directory tr.odd {\n    background-color: transparent;\n}\n\n.icona {\n    width: auto;\n    height: auto;\n    margin: 0 var(--spacing-small);\n}\n\n.icon {\n    background: var(--primary-color);\n    border-radius: var(--border-radius-small);\n    font-size: var(--page-font-size);\n    padding: calc(var(--page-font-size) / 5);\n    line-height: var(--page-font-size);\n    transform: scale(0.8);\n    height: auto;\n    width: var(--page-font-size);\n    user-select: none;\n}\n\n.iconfopen, .icondoc, .iconfclosed {\n    background-position: center;\n    margin-bottom: 0;\n    height: var(--table-line-height);\n}\n\n.icondoc {\n    filter: saturate(0.2);\n}\n\n@media screen and (max-width: 767px) {\n    div.directory {\n        margin-left: calc(0px - var(--spacing-large));\n        margin-right: calc(0px - var(--spacing-large));\n    }\n}\n\n@media (prefers-color-scheme: dark) {\n    html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed {\n        filter: hue-rotate(180deg) invert();\n    }\n}\n\nhtml.dark-mode .iconfopen, html.dark-mode .iconfclosed {\n    filter: hue-rotate(180deg) invert();\n}\n\n/*\n Class list\n */\n\n.classindex dl.odd {\n    background: var(--odd-color);\n    border-radius: var(--border-radius-small);\n}\n\n.classindex dl.even {\n    background-color: transparent;\n}\n\n/*\n Class Index Doxygen 1.8\n*/\n\ntable.classindex {\n    margin-left: 0;\n    margin-right: 0;\n    width: 100%;\n}\n\ntable.classindex table div.ah {\n    background-image: none;\n    background-color: initial;\n    border-color: var(--separator-color);\n    color: var(--page-foreground-color);\n    box-shadow: var(--box-shadow);\n    border-radius: var(--border-radius-large);\n    padding: var(--spacing-small);\n}\n\ndiv.qindex {\n    background-color: var(--odd-color);\n    border-radius: var(--border-radius-small);\n    border: 1px solid var(--separator-color);\n    padding: var(--spacing-small) 0;\n}\n\n/*\n  Footer and nav-path\n */\n\n#nav-path {\n    width: 100%;\n}\n\n#nav-path ul {\n    background-image: none;\n    background: var(--page-background-color);\n    border: none;\n    border-top: 1px solid var(--separator-color);\n    border-bottom: 0;\n    font-size: var(--navigation-font-size);\n}\n\nimg.footer {\n    width: 60px;\n}\n\n.navpath li.footer {\n    color: var(--page-secondary-foreground-color);\n}\n\naddress.footer {\n    color: var(--page-secondary-foreground-color);\n    margin-bottom: var(--spacing-large);\n}\n\n#nav-path li.navelem {\n    background-image: none;\n    display: flex;\n    align-items: center;\n}\n\n.navpath li.navelem a {\n    text-shadow: none;\n    display: inline-block;\n    color: var(--primary-color) !important;\n}\n\n.navpath li.navelem a:hover {\n    text-shadow: none;\n}\n\n.navpath li.navelem b {\n    color: var(--primary-dark-color);\n    font-weight: 500;\n}\n\nli.navelem {\n    padding: 0;\n    margin-left: -8px;\n}\n\nli.navelem:first-child {\n    margin-left: var(--spacing-large);\n}\n\nli.navelem:first-child:before {\n    display: none;\n}\n\n#nav-path ul {\n    padding-left: 0;\n}\n\n#nav-path li.navelem:has(.el):after {\n    content: '';\n    border: 5px solid var(--page-background-color);\n    border-bottom-color: transparent;\n    border-right-color: transparent;\n    border-top-color: transparent;\n    transform: translateY(-1px) scaleY(4.2);\n    z-index: 10;\n    margin-left: 6px;\n}\n\n#nav-path li.navelem:not(:has(.el)):after {\n    background: var(--page-background-color);\n    box-shadow: 1px -1px 0 1px var(--separator-color);\n    border-radius: 0 var(--border-radius-medium) 0 50px;\n}\n\n#nav-path li.navelem:not(:has(.el)) {\n    margin-left: 0;\n}\n\n#nav-path li.navelem:not(:has(.el)):hover, #nav-path li.navelem:not(:has(.el)):hover:after {\n    background-color: var(--separator-color);\n}\n\n#nav-path li.navelem:has(.el):before {\n    content: '';\n    border: 5px solid var(--separator-color);\n    border-bottom-color: transparent;\n    border-right-color: transparent;\n    border-top-color: transparent;\n    transform: translateY(-1px) scaleY(3.2);\n    margin-right: var(--spacing-small);\n}\n\n.navpath li.navelem a:hover {\n    color: var(--primary-color);\n}\n\n/*\n Scrollbars for Webkit\n*/\n\n#nav-tree::-webkit-scrollbar,\ndiv.fragment::-webkit-scrollbar,\npre.fragment::-webkit-scrollbar,\ndiv.memproto::-webkit-scrollbar,\n.contents center::-webkit-scrollbar,\n.contents .center::-webkit-scrollbar,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar,\ndiv.contents .toc::-webkit-scrollbar,\n.contents .dotgraph::-webkit-scrollbar,\n.contents .tabs-overview-container::-webkit-scrollbar {\n    background: transparent;\n    width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));\n    height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));\n}\n\n#nav-tree::-webkit-scrollbar-thumb,\ndiv.fragment::-webkit-scrollbar-thumb,\npre.fragment::-webkit-scrollbar-thumb,\ndiv.memproto::-webkit-scrollbar-thumb,\n.contents center::-webkit-scrollbar-thumb,\n.contents .center::-webkit-scrollbar-thumb,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb,\ndiv.contents .toc::-webkit-scrollbar-thumb,\n.contents .dotgraph::-webkit-scrollbar-thumb,\n.contents .tabs-overview-container::-webkit-scrollbar-thumb {\n    background-color: transparent;\n    border: var(--webkit-scrollbar-padding) solid transparent;\n    border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));\n    background-clip: padding-box;\n}\n\n#nav-tree:hover::-webkit-scrollbar-thumb,\ndiv.fragment:hover::-webkit-scrollbar-thumb,\npre.fragment:hover::-webkit-scrollbar-thumb,\ndiv.memproto:hover::-webkit-scrollbar-thumb,\n.contents center:hover::-webkit-scrollbar-thumb,\n.contents .center:hover::-webkit-scrollbar-thumb,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb,\ndiv.contents .toc:hover::-webkit-scrollbar-thumb,\n.contents .dotgraph:hover::-webkit-scrollbar-thumb,\n.contents .tabs-overview-container:hover::-webkit-scrollbar-thumb {\n    background-color: var(--webkit-scrollbar-color);\n}\n\n#nav-tree::-webkit-scrollbar-track,\ndiv.fragment::-webkit-scrollbar-track,\npre.fragment::-webkit-scrollbar-track,\ndiv.memproto::-webkit-scrollbar-track,\n.contents center::-webkit-scrollbar-track,\n.contents .center::-webkit-scrollbar-track,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track,\ndiv.contents .toc::-webkit-scrollbar-track,\n.contents .dotgraph::-webkit-scrollbar-track,\n.contents .tabs-overview-container::-webkit-scrollbar-track {\n    background: transparent;\n}\n\n#nav-tree::-webkit-scrollbar-corner {\n    background-color: var(--side-nav-background);\n}\n\n#nav-tree,\ndiv.fragment,\npre.fragment,\ndiv.memproto,\n.contents center,\n.contents .center,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody,\ndiv.contents .toc {\n    overflow-x: auto;\n    overflow-x: overlay;\n}\n\n#nav-tree {\n    overflow-x: auto;\n    overflow-y: auto;\n    overflow-y: overlay;\n}\n\n/*\n Scrollbars for Firefox\n*/\n\n#nav-tree,\ndiv.fragment,\npre.fragment,\ndiv.memproto,\n.contents center,\n.contents .center,\n.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody,\ndiv.contents .toc,\n.contents .dotgraph,\n.contents .tabs-overview-container {\n    scrollbar-width: thin;\n}\n\n/*\n  Optional Dark mode toggle button\n*/\n\ndoxygen-awesome-dark-mode-toggle {\n    display: inline-block;\n    margin: 0 0 0 var(--spacing-small);\n    padding: 0;\n    width: var(--searchbar-height);\n    height: var(--searchbar-height);\n    background: none;\n    border: none;\n    border-radius: var(--searchbar-border-radius);\n    vertical-align: middle;\n    text-align: center;\n    line-height: var(--searchbar-height);\n    font-size: 22px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    user-select: none;\n    cursor: pointer;\n}\n\ndoxygen-awesome-dark-mode-toggle > svg {\n    transition: transform var(--animation-duration) ease-in-out;\n}\n\ndoxygen-awesome-dark-mode-toggle:active > svg {\n    transform: scale(.5);\n}\n\ndoxygen-awesome-dark-mode-toggle:hover {\n    background-color: rgba(0,0,0,.03);\n}\n\nhtml.dark-mode doxygen-awesome-dark-mode-toggle:hover {\n    background-color: rgba(0,0,0,.18);\n}\n\n/*\n Optional fragment copy button\n*/\n.doxygen-awesome-fragment-wrapper {\n    position: relative;\n}\n\ndoxygen-awesome-fragment-copy-button {\n    opacity: 0;\n    background: var(--fragment-background);\n    width: 28px;\n    height: 28px;\n    position: absolute;\n    right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5));\n    top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5));\n    border: 1px solid var(--fragment-foreground);\n    cursor: pointer;\n    border-radius: var(--border-radius-small);\n    display: flex;\n    justify-content: center;\n    align-items: center;\n}\n\n.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success {\n    opacity: .28;\n}\n\ndoxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success {\n    opacity: 1 !important;\n}\n\ndoxygen-awesome-fragment-copy-button:active:not([class~=success]) svg {\n    transform: scale(.91);\n}\n\ndoxygen-awesome-fragment-copy-button svg {\n    fill: var(--fragment-foreground);\n    width: 18px;\n    height: 18px;\n}\n\ndoxygen-awesome-fragment-copy-button.success svg {\n    fill: rgb(14, 168, 14);\n}\n\ndoxygen-awesome-fragment-copy-button.success {\n    border-color: rgb(14, 168, 14);\n}\n\n@media screen and (max-width: 767px) {\n    .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,\n    .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,\n    .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,\n    .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,\n    dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button {\n        right: 0;\n    }\n}\n\n/*\n Optional paragraph link button\n*/\n\na.anchorlink {\n    font-size: 90%;\n    margin-left: var(--spacing-small);\n    color: var(--page-foreground-color) !important;\n    text-decoration: none;\n    opacity: .15;\n    display: none;\n    transition: opacity var(--animation-duration) ease-in-out, color var(--animation-duration) ease-in-out;\n}\n\na.anchorlink svg {\n    fill: var(--page-foreground-color);\n}\n\nh3 a.anchorlink svg, h4 a.anchorlink svg {\n    margin-bottom: -3px;\n    margin-top: -4px;\n}\n\na.anchorlink:hover {\n    opacity: .45;\n}\n\nh2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink  {\n    display: inline-block;\n}\n\n/*\n Optional tab feature\n*/\n\n.tabbed > ul {\n    padding-inline-start: 0px;\n    margin: 0;\n    padding: var(--spacing-small) 0;\n}\n\n.tabbed > ul > li {\n    display: none;\n}\n\n.tabbed > ul > li.selected {\n    display: block;\n}\n\n.tabs-overview-container {\n    overflow-x: auto;\n    display: block;\n    overflow-y: visible;\n}\n\n.tabs-overview {\n    border-bottom: 1px solid var(--separator-color);\n    display: flex;\n    flex-direction: row;\n}\n\n@media screen and (max-width: 767px) {\n    .tabs-overview-container {\n        margin: 0 calc(0px - var(--spacing-large));\n    }\n    .tabs-overview {\n        padding: 0 var(--spacing-large)\n    }\n}\n\n.tabs-overview button.tab-button {\n    color: var(--page-foreground-color);\n    margin: 0;\n    border: none;\n    background: transparent;\n    padding: calc(var(--spacing-large) / 2) 0;\n    display: inline-block;\n    font-size: var(--page-font-size);\n    cursor: pointer;\n    box-shadow: 0 1px 0 0 var(--separator-color);\n    position: relative;\n\n    -webkit-tap-highlight-color: transparent;\n}\n\n.tabs-overview button.tab-button .tab-title::before {\n    display: block;\n    content: attr(title);\n    font-weight: 600;\n    height: 0;\n    overflow: hidden;\n    visibility: hidden;\n}\n\n.tabs-overview button.tab-button .tab-title {\n    float: left;\n    white-space: nowrap;\n    font-weight: normal;\n    font-family: var(--font-family);\n    padding: calc(var(--spacing-large) / 2) var(--spacing-large);\n    border-radius: var(--border-radius-medium);\n    transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out;\n}\n\n.tabs-overview button.tab-button:not(:last-child) .tab-title {\n    box-shadow: 8px 0 0 -7px var(--separator-color);\n}\n\n.tabs-overview button.tab-button:hover .tab-title {\n    background: var(--separator-color);\n    box-shadow: none;\n}\n\n.tabs-overview button.tab-button.active .tab-title {\n    font-weight: 600;\n}\n\n.tabs-overview button.tab-button::after {\n    content: '';\n    display: block;\n    position: absolute;\n    left: 0;\n    bottom: 0;\n    right: 0;\n    height: 0;\n    width: 0%;\n    margin: 0 auto;\n    border-radius: var(--border-radius-small) var(--border-radius-small) 0 0;\n    background-color: var(--primary-color);\n    transition: width var(--animation-duration) ease-in-out, height var(--animation-duration) ease-in-out;\n}\n\n.tabs-overview button.tab-button.active::after {\n    width: 100%;\n    box-sizing: border-box;\n    height: 3px;\n}\n\n\n/*\n Navigation Buttons\n*/\n\n.section_buttons:not(:empty) {\n    margin-top: calc(var(--spacing-large) * 3);\n}\n\n.section_buttons table.markdownTable {\n    display: block;\n    width: 100%;\n}\n\n.section_buttons table.markdownTable tbody {\n    display: table !important;\n    width: 100%;\n    box-shadow: none;\n    border-spacing: 10px;\n}\n\n.section_buttons table.markdownTable td {\n    padding: 0;\n}\n\n.section_buttons table.markdownTable th {\n    display: none;\n}\n\n.section_buttons table.markdownTable tr.markdownTableHead {\n    border: none;\n}\n\n.section_buttons tr th, .section_buttons tr td {\n    background: none;\n    border: none;\n    padding: var(--spacing-large) 0 var(--spacing-small);\n}\n\n.section_buttons a {\n    display: inline-block;\n    border: 1px solid var(--separator-color);\n    border-radius: var(--border-radius-medium);\n    color: var(--page-secondary-foreground-color) !important;\n    text-decoration: none;\n    transition: color var(--animation-duration) ease-in-out, background-color var(--animation-duration) ease-in-out;\n}\n\n.section_buttons a:hover {\n    color: var(--page-foreground-color) !important;\n    background-color: var(--odd-color);\n}\n\n.section_buttons tr td.markdownTableBodyLeft a {\n    padding: var(--spacing-medium) var(--spacing-large) var(--spacing-medium) calc(var(--spacing-large) / 2);\n}\n\n.section_buttons tr td.markdownTableBodyRight a {\n    padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large);\n}\n\n.section_buttons tr td.markdownTableBodyLeft a::before,\n.section_buttons tr td.markdownTableBodyRight a::after {\n    color: var(--page-secondary-foreground-color) !important;\n    display: inline-block;\n    transition: color .08s ease-in-out, transform .09s ease-in-out;\n}\n\n.section_buttons tr td.markdownTableBodyLeft a::before {\n    content: '〈';\n    padding-right: var(--spacing-large);\n}\n\n\n.section_buttons tr td.markdownTableBodyRight a::after {\n    content: '〉';\n    padding-left: var(--spacing-large);\n}\n\n\n.section_buttons tr td.markdownTableBodyLeft a:hover::before {\n    color: var(--page-foreground-color) !important;\n    transform: translateX(-3px);\n}\n\n.section_buttons tr td.markdownTableBodyRight a:hover::after {\n    color: var(--page-foreground-color) !important;\n    transform: translateX(3px);\n}\n\n@media screen and (max-width: 450px) {\n    .section_buttons a {\n        width: 100%;\n        box-sizing: border-box;\n    }\n\n    .section_buttons tr td:nth-of-type(1).markdownTableBodyLeft a {\n        border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium);\n        border-right: none;\n    }\n\n    .section_buttons tr td:nth-of-type(2).markdownTableBodyRight a {\n        border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0;\n    }\n}\n\n/*\n Bordered image\n*/\n\nhtml.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */\nhtml.dark-mode .darkmode_inverted_image object[type=\"image/svg+xml\"] /* doxygen 1.9.3 */ {\n    filter: brightness(89%) hue-rotate(180deg) invert();\n}\n\n.bordered_image {\n    border-radius: var(--border-radius-small);\n    border: 1px solid var(--separator-color);\n    display: inline-block;\n    overflow: hidden;\n}\n\n.bordered_image:empty {\n    border: none;\n}\n\nhtml.dark-mode .bordered_image img, /* < doxygen 1.9.3 */\nhtml.dark-mode .bordered_image object[type=\"image/svg+xml\"] /* doxygen 1.9.3 */ {\n    border-radius: var(--border-radius-small);\n}\n\n/*\n Button\n*/\n\n.primary-button {\n    display: inline-block;\n    cursor: pointer;\n    background: var(--primary-color);\n    color: var(--page-background-color) !important;\n    border-radius: var(--border-radius-medium);\n    padding: var(--spacing-small) var(--spacing-medium);\n    text-decoration: none;\n}\n\n.primary-button:hover {\n    background: var(--primary-dark-color);\n}\n"
  },
  {
    "path": "examples/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.12)\n\n# Macro to add example executables\nmacro(add_example EXAMPLE_NAME)\n    add_executable(${EXAMPLE_NAME} ${EXAMPLE_NAME}.cpp)\n    target_link_libraries(${EXAMPLE_NAME} dispenso)\n    target_compile_features(${EXAMPLE_NAME} PRIVATE cxx_std_14)\nendmacro()\n\n# Add all examples\nadd_example(parallel_for_example)\nadd_example(for_each_example)\nadd_example(task_set_example)\nadd_example(future_example)\nadd_example(graph_example)\nadd_example(pipeline_example)\nadd_example(concurrent_vector_example)\nadd_example(latch_example)\nadd_example(resource_pool_example)\n"
  },
  {
    "path": "examples/concurrent_vector_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example concurrent_vector_example.cpp\n * Demonstrates thread-safe vector operations with dispenso::ConcurrentVector.\n */\n\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/parallel_for.h>\n\n#include <algorithm>\n#include <iostream>\n#include <numeric>\n\nint main() {\n  // Example 1: Basic concurrent push_back\n  std::cout << \"Example 1: Concurrent push_back from multiple threads\\n\";\n  {\n    dispenso::ConcurrentVector<int> vec;\n\n    // Push elements concurrently\n    dispenso::parallel_for(0, 1000, [&vec](size_t i) { vec.push_back(static_cast<int>(i)); });\n\n    std::cout << \"  Vector size after concurrent pushes: \" << vec.size() << \"\\n\";\n    std::cout << \"  (Note: order may vary due to concurrent access)\\n\";\n  }\n\n  // Example 2: grow_by for batch insertion\n  std::cout << \"\\nExample 2: grow_by for efficient batch insertion\\n\";\n  {\n    dispenso::ConcurrentVector<double> vec;\n\n    // Each thread grows the vector by a batch\n    dispenso::parallel_for(0, 10, [&vec](size_t threadId) {\n      auto it = vec.grow_by(100, static_cast<double>(threadId));\n      (void)it; // Iterator points to start of grown range\n    });\n\n    std::cout << \"  Vector size: \" << vec.size() << \" (expected: 1000)\\n\";\n\n    // Count occurrences\n    std::array<int, 10> counts = {0};\n    for (double val : vec) {\n      counts[static_cast<size_t>(val)]++;\n    }\n    std::cout << \"  Each thread's value appears 100 times: \";\n    std::cout << (std::all_of(counts.begin(), counts.end(), [](int c) { return c == 100; }) ? \"yes\"\n                                                                                            : \"no\")\n              << \"\\n\";\n  }\n\n  // Example 3: Using grow_by_generator\n  std::cout << \"\\nExample 3: grow_by_generator with custom initialization\\n\";\n  {\n    dispenso::ConcurrentVector<int> vec;\n\n    // Grow with a generator function\n    int startValue = 0;\n    vec.grow_by_generator(10, [&startValue]() { return startValue++; });\n\n    std::cout << \"  Generated values: \";\n    for (int val : vec) {\n      std::cout << val << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 4: grow_to_at_least\n  std::cout << \"\\nExample 4: grow_to_at_least for minimum size guarantee\\n\";\n  {\n    dispenso::ConcurrentVector<int> vec;\n\n    // Multiple threads try to ensure minimum size\n    dispenso::parallel_for(0, 10, [&vec](size_t i) {\n      size_t requiredSize = (i + 1) * 100;\n      vec.grow_to_at_least(requiredSize, -1);\n    });\n\n    std::cout << \"  Vector size: \" << vec.size() << \" (at least 1000)\\n\";\n  }\n\n  // Example 5: Reserving capacity with ReserveTag\n  std::cout << \"\\nExample 5: Reserving capacity for better performance\\n\";\n  {\n    // Reserve space upfront for better memory allocation\n    dispenso::ConcurrentVector<int> vec(10000, dispenso::ReserveTag);\n\n    std::cout << \"  Capacity after reserve: \" << vec.capacity() << \"\\n\";\n    std::cout << \"  Size (still empty): \" << vec.size() << \"\\n\";\n\n    // Now concurrent operations will be faster\n    dispenso::parallel_for(0, 5000, [&vec](size_t i) { vec.push_back(static_cast<int>(i)); });\n\n    std::cout << \"  Size after pushes: \" << vec.size() << \"\\n\";\n  }\n\n  // Example 6: Iterator stability\n  std::cout << \"\\nExample 6: Iterator stability during concurrent modification\\n\";\n  {\n    dispenso::ConcurrentVector<int> vec;\n    vec.push_back(1);\n    vec.push_back(2);\n    vec.push_back(3);\n\n    // Get iterators to existing elements\n    auto it = vec.begin();\n    int& firstElement = *it;\n\n    // Push more elements concurrently\n    dispenso::parallel_for(0, 100, [&vec](size_t i) { vec.push_back(static_cast<int>(i + 100)); });\n\n    // Original iterator and reference are still valid\n    std::cout << \"  First element via original iterator: \" << *it << \"\\n\";\n    std::cout << \"  First element via original reference: \" << firstElement << \"\\n\";\n    std::cout << \"  Vector size now: \" << vec.size() << \"\\n\";\n  }\n\n  // Example 7: Standard container operations\n  std::cout << \"\\nExample 7: Standard container operations\\n\";\n  {\n    dispenso::ConcurrentVector<int> vec = {5, 3, 1, 4, 2};\n\n    // Sorting (not concurrent - use single thread)\n    std::sort(vec.begin(), vec.end());\n\n    std::cout << \"  Sorted: \";\n    for (int val : vec) {\n      std::cout << val << \" \";\n    }\n    std::cout << \"\\n\";\n\n    // Access by index\n    std::cout << \"  vec[2] = \" << vec[2] << \"\\n\";\n\n    // Front and back\n    std::cout << \"  front() = \" << vec.front() << \", back() = \" << vec.back() << \"\\n\";\n  }\n\n  // Example 8: Copy and move semantics\n  std::cout << \"\\nExample 8: Copy and move semantics\\n\";\n  {\n    dispenso::ConcurrentVector<int> original = {1, 2, 3, 4, 5};\n\n    // Copy\n    dispenso::ConcurrentVector<int> copied = original;\n    std::cout << \"  Original size: \" << original.size() << \", Copy size: \" << copied.size() << \"\\n\";\n\n    // Move\n    dispenso::ConcurrentVector<int> moved = std::move(original);\n    std::cout << \"  After move - Original size: \" << original.size()\n              << \", Moved size: \" << moved.size() << \"\\n\";\n  }\n\n  std::cout << \"\\nAll ConcurrentVector examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/for_each_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example for_each_example.cpp\n * Demonstrates parallel iteration over containers using dispenso::for_each.\n */\n\n#include <dispenso/for_each.h>\n\n#include <cmath>\n#include <iostream>\n#include <list>\n#include <vector>\n\nint main() {\n  // Example 1: for_each on a vector\n  std::cout << \"Example 1: for_each on a vector\\n\";\n  std::vector<double> values = {1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0};\n\n  // Apply square root to each element in parallel\n  dispenso::for_each(values.begin(), values.end(), [](double& val) { val = std::sqrt(val); });\n\n  std::cout << \"  Square roots: \";\n  for (double v : values) {\n    std::cout << v << \" \";\n  }\n  std::cout << \"\\n\";\n\n  // Example 2: for_each on a list (non-contiguous memory)\n  std::cout << \"\\nExample 2: for_each on a std::list\\n\";\n  std::list<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n\n  // Double each value in parallel\n  dispenso::for_each(numbers.begin(), numbers.end(), [](int& n) { n *= 2; });\n\n  std::cout << \"  Doubled values: \";\n  for (int n : numbers) {\n    std::cout << n << \" \";\n  }\n  std::cout << \"\\n\";\n\n  // Example 3: for_each_n with a count\n  std::cout << \"\\nExample 3: for_each_n with explicit count\\n\";\n  std::vector<int> partial = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};\n\n  // Only process first 5 elements\n  dispenso::for_each_n(partial.begin(), 5, [](int& n) { n += 100; });\n\n  std::cout << \"  After adding 100 to first 5: \";\n  for (int n : partial) {\n    std::cout << n << \" \";\n  }\n  std::cout << \"\\n\";\n\n  // Example 4: for_each with a TaskSet for external synchronization\n  std::cout << \"\\nExample 4: for_each with explicit TaskSet\\n\";\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n  std::vector<int> data = {1, 2, 3, 4, 5};\n\n  // Use options to control behavior\n  dispenso::ForEachOptions options;\n  options.wait = true;\n\n  dispenso::for_each(taskSet, data.begin(), data.end(), [](int& n) { n = n * n; }, options);\n\n  std::cout << \"  Squared values: \";\n  for (int n : data) {\n    std::cout << n << \" \";\n  }\n  std::cout << \"\\n\";\n\n  // Example 5: for_each with limited parallelism\n  std::cout << \"\\nExample 5: for_each with limited parallelism\\n\";\n  std::vector<int> limited(100, 1);\n\n  dispenso::ForEachOptions limitedOptions;\n  limitedOptions.maxThreads = 2;\n\n  dispenso::for_each(limited.begin(), limited.end(), [](int& n) { n += 1; }, limitedOptions);\n\n  std::cout << \"  First few values: \" << limited[0] << \" \" << limited[1] << \" \" << limited[2]\n            << \" (all should be 2)\\n\";\n\n  std::cout << \"\\nAll for_each examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/future_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example future_example.cpp\n * Demonstrates creating and chaining futures with dispenso::Future.\n */\n\n#include <dispenso/future.h>\n\n#include <chrono>\n#include <cmath>\n#include <iostream>\n#include <thread>\n\nint main() {\n  // Example 1: Basic async execution\n  std::cout << \"Example 1: Basic async execution\\n\";\n  {\n    // Launch an async computation\n    dispenso::Future<int> future = dispenso::async([]() {\n      // Simulate some work\n      int result = 0;\n      for (int i = 1; i <= 100; ++i) {\n        result += i;\n      }\n      return result;\n    });\n\n    // Do other work while computation runs...\n    std::cout << \"  Computing sum of 1..100 asynchronously...\\n\";\n\n    // Get the result (blocks until ready)\n    int result = future.get();\n    std::cout << \"  Result: \" << result << \" (expected: 5050)\\n\";\n  }\n\n  // Example 2: Chaining futures with then()\n  std::cout << \"\\nExample 2: Chaining futures with then()\\n\";\n  {\n    dispenso::Future<double> chainedFuture = dispenso::async([]() {\n                                               return 16.0; // First computation\n                                             })\n                                                 .then([](dispenso::Future<double>&& prev) {\n                                                   return std::sqrt(prev.get()); // Chain: take sqrt\n                                                 })\n                                                 .then([](dispenso::Future<double>&& prev) {\n                                                   return prev.get() * 2.0; // Chain: multiply by 2\n                                                 });\n\n    std::cout << \"  sqrt(16) * 2 = \" << chainedFuture.get() << \" (expected: 8)\\n\";\n  }\n\n  // Example 3: make_ready_future for immediate values\n  std::cout << \"\\nExample 3: make_ready_future for immediate values\\n\";\n  {\n    // Create a future that's already ready\n    dispenso::Future<std::string> ready = dispenso::make_ready_future(std::string(\"Hello, World!\"));\n\n    std::cout << \"  is_ready: \" << (ready.is_ready() ? \"true\" : \"false\") << \"\\n\";\n    std::cout << \"  Value: \" << ready.get() << \"\\n\";\n  }\n\n  // Example 4: wait_for with timeout\n  std::cout << \"\\nExample 4: wait_for with timeout\\n\";\n  {\n    dispenso::Future<int> slowFuture = dispenso::async(std::launch::async, []() {\n      std::this_thread::sleep_for(std::chrono::milliseconds(100));\n      return 42;\n    });\n\n    // Try to wait with a short timeout\n    auto status = slowFuture.wait_for(std::chrono::milliseconds(10));\n    std::cout << \"  After 10ms wait: \"\n              << (status == std::future_status::ready ? \"ready\" : \"timeout\") << \"\\n\";\n\n    // Wait for completion\n    slowFuture.wait();\n    std::cout << \"  After full wait: \" << slowFuture.get() << \"\\n\";\n  }\n\n  // Example 5: when_all to wait for multiple futures\n  std::cout << \"\\nExample 5: when_all for multiple futures\\n\";\n  {\n    dispenso::Future<int> f1 = dispenso::async([]() { return 10; });\n    dispenso::Future<int> f2 = dispenso::async([]() { return 20; });\n    dispenso::Future<int> f3 = dispenso::async([]() { return 30; });\n\n    // Wait for all futures to complete\n    auto allFutures = dispenso::when_all(std::move(f1), std::move(f2), std::move(f3));\n\n    // Get the results\n    auto tuple = allFutures.get();\n    int sum = std::get<0>(tuple).get() + std::get<1>(tuple).get() + std::get<2>(tuple).get();\n\n    std::cout << \"  Sum of all futures: \" << sum << \" (expected: 60)\\n\";\n  }\n\n  // Example 6: Using Future with a custom thread pool\n  std::cout << \"\\nExample 6: Future with custom ThreadPool\\n\";\n  {\n    dispenso::ThreadPool customPool(2);\n\n    dispenso::Future<double> future = dispenso::async(customPool, []() { return 3.14159; });\n\n    std::cout << \"  Pi from custom pool: \" << future.get() << \"\\n\";\n  }\n\n  // Example 7: Future<void> for side effects\n  std::cout << \"\\nExample 7: Future<void> for side effects\\n\";\n  {\n    int sideEffectValue = 0;\n\n    dispenso::Future<void> voidFuture = dispenso::async([&sideEffectValue]() {\n      sideEffectValue = 123;\n      // No return value\n    });\n\n    voidFuture.get(); // Wait for completion\n\n    std::cout << \"  Side effect value: \" << sideEffectValue << \"\\n\";\n  }\n\n  std::cout << \"\\nAll Future examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/graph_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example graph_example.cpp\n * Demonstrates task graphs with dependencies using dispenso::Graph.\n */\n\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n\n#include <array>\n#include <iostream>\n\nint main() {\n  // Example 1: Simple linear dependency chain\n  std::cout << \"Example 1: Linear dependency chain (A -> B -> C)\\n\";\n  {\n    std::array<int, 3> values = {0, 0, 0};\n\n    dispenso::Graph graph;\n\n    dispenso::Node& nodeA = graph.addNode([&]() {\n      values[0] = 1;\n      std::cout << \"  Node A: set values[0] = 1\\n\";\n    });\n\n    dispenso::Node& nodeB = graph.addNode([&]() {\n      values[1] = values[0] * 2;\n      std::cout << \"  Node B: set values[1] = values[0] * 2 = \" << values[1] << \"\\n\";\n    });\n\n    dispenso::Node& nodeC = graph.addNode([&]() {\n      values[2] = values[1] + 10;\n      std::cout << \"  Node C: set values[2] = values[1] + 10 = \" << values[2] << \"\\n\";\n    });\n\n    // Set up dependencies: B depends on A, C depends on B\n    nodeB.dependsOn(nodeA);\n    nodeC.dependsOn(nodeB);\n\n    // Initialize predecessor counts and execute the graph\n    setAllNodesIncomplete(graph);\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    executor(taskSet, graph);\n\n    std::cout << \"  Final values: \" << values[0] << \", \" << values[1] << \", \" << values[2] << \"\\n\";\n  }\n\n  // Example 2: Diamond dependency pattern\n  std::cout << \"\\nExample 2: Diamond dependency pattern\\n\";\n  {\n    //         A\n    //        / \\\n    //       B   C\n    //        \\ /\n    //         D\n    std::array<float, 5> r = {0, 0, 0, 0, 0};\n\n    dispenso::Graph graph;\n\n    dispenso::Node& A = graph.addNode([&]() {\n      r[0] = 1.0f;\n      std::cout << \"  A: r[0] = \" << r[0] << \"\\n\";\n    });\n\n    dispenso::Node& B = graph.addNode([&]() {\n      r[1] = r[0] * 2.0f;\n      std::cout << \"  B: r[1] = r[0] * 2 = \" << r[1] << \"\\n\";\n    });\n\n    dispenso::Node& C = graph.addNode([&]() {\n      r[2] = r[0] + 5.0f;\n      std::cout << \"  C: r[2] = r[0] + 5 = \" << r[2] << \"\\n\";\n    });\n\n    dispenso::Node& D = graph.addNode([&]() {\n      r[3] = r[1] + r[2];\n      std::cout << \"  D: r[3] = r[1] + r[2] = \" << r[3] << \"\\n\";\n    });\n\n    // Diamond pattern dependencies\n    B.dependsOn(A);\n    C.dependsOn(A);\n    D.dependsOn(B, C);\n\n    // Initialize predecessor counts and execute\n    setAllNodesIncomplete(graph);\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    executor(taskSet, graph);\n\n    std::cout << \"  Expected r[3] = 2 + 6 = 8, got: \" << r[3] << \"\\n\";\n  }\n\n  // Example 3: Graph re-execution with setAllNodesIncomplete\n  std::cout << \"\\nExample 3: Re-executing a graph\\n\";\n  {\n    int counter = 0;\n\n    dispenso::Graph graph;\n\n    dispenso::Node& node = graph.addNode([&]() {\n      counter++;\n      std::cout << \"  Executed, counter = \" << counter << \"\\n\";\n    });\n    (void)node;\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n\n    // First execution - need to initialize predecessor counts\n    std::cout << \"  First execution:\\n\";\n    setAllNodesIncomplete(graph);\n    executor(taskSet, graph);\n\n    // Reset and execute again\n    std::cout << \"  Second execution (after setAllNodesIncomplete):\\n\";\n    setAllNodesIncomplete(graph);\n    executor(taskSet, graph);\n\n    std::cout << \"  Final counter = \" << counter << \" (expected: 2)\\n\";\n  }\n\n  // Example 4: Using subgraphs\n  std::cout << \"\\nExample 4: Using subgraphs\\n\";\n  {\n    std::array<float, 4> r = {0, 0, 0, 0};\n\n    dispenso::Graph graph;\n\n    // Create two subgraphs for different parts of computation\n    dispenso::Subgraph& inputSubgraph = graph.addSubgraph();\n    dispenso::Subgraph& processSubgraph = graph.addSubgraph();\n\n    // Input nodes\n    dispenso::Node& inputA = inputSubgraph.addNode([&]() { r[0] = 10.0f; });\n    dispenso::Node& inputB = inputSubgraph.addNode([&]() { r[1] = 20.0f; });\n\n    // Processing nodes\n    dispenso::Node& sum = processSubgraph.addNode([&]() { r[2] = r[0] + r[1]; });\n\n    // Output node in main graph\n    dispenso::Node& output = graph.addNode([&]() { r[3] = r[2] * 2.0f; });\n\n    // Set dependencies\n    sum.dependsOn(inputA, inputB);\n    output.dependsOn(sum);\n\n    // Initialize predecessor counts and execute\n    setAllNodesIncomplete(graph);\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    executor(taskSet, graph);\n\n    std::cout << \"  r[0]=\" << r[0] << \", r[1]=\" << r[1] << \", r[2]=\" << r[2] << \", r[3]=\" << r[3]\n              << \"\\n\";\n    std::cout << \"  Expected r[3] = (10+20)*2 = 60\\n\";\n  }\n\n  // Example 5: Partial graph re-evaluation\n  std::cout << \"\\nExample 5: Partial graph re-evaluation\\n\";\n  {\n    std::array<int, 3> data = {1, 0, 0};\n    std::array<int, 3> execCount = {0, 0, 0};\n\n    dispenso::Graph graph;\n\n    dispenso::Node& A = graph.addNode([&]() {\n      data[0] = data[0] * 2;\n      execCount[0]++;\n    });\n\n    dispenso::Node& B = graph.addNode([&]() {\n      data[1] = data[0] + 10;\n      execCount[1]++;\n    });\n\n    dispenso::Node& C = graph.addNode([&]() {\n      data[2] = data[1] + 100;\n      execCount[2]++;\n    });\n\n    B.dependsOn(A);\n    C.dependsOn(B);\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n\n    // First execution - initialize predecessor counts\n    setAllNodesIncomplete(graph);\n    executor(taskSet, graph);\n    std::cout << \"  After first run: data = [\" << data[0] << \", \" << data[1] << \", \" << data[2]\n              << \"]\\n\";\n\n    // Mark only B as incomplete (and propagate to C)\n    B.setIncomplete();\n    dispenso::ForwardPropagator propagator;\n    propagator(graph);\n\n    // Change input to B\n    data[0] = 5;\n\n    // Re-execute - only B and C should run\n    executor(taskSet, graph);\n    std::cout << \"  After partial run: data = [\" << data[0] << \", \" << data[1] << \", \" << data[2]\n              << \"]\\n\";\n    std::cout << \"  Execution counts: A=\" << execCount[0] << \", B=\" << execCount[1]\n              << \", C=\" << execCount[2] << \"\\n\";\n  }\n\n  std::cout << \"\\nAll Graph examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/latch_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example latch_example.cpp\n * Demonstrates thread synchronization with dispenso::Latch.\n */\n\n#include <dispenso/latch.h>\n#include <dispenso/parallel_for.h>\n#include <dispenso/thread_pool.h>\n\n#include <atomic>\n#include <iostream>\n#include <thread>\n#include <vector>\n\nint main() {\n  // Example 1: Basic latch synchronization\n  std::cout << \"Example 1: Basic latch synchronization\\n\";\n  {\n    constexpr int kNumThreads = 4;\n    dispenso::Latch latch(kNumThreads);\n    std::atomic<int> readyCount(0);\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    for (int i = 0; i < kNumThreads; ++i) {\n      taskSet.schedule([&latch, &readyCount, i]() {\n        // Simulate some initialization work\n        readyCount.fetch_add(1, std::memory_order_relaxed);\n        std::cout << \"  Thread \" << i << \" ready\\n\";\n\n        // Signal completion and wait for others\n        latch.arrive_and_wait();\n\n        // All threads are synchronized here\n      });\n    }\n\n    taskSet.wait();\n\n    std::cout << \"  All \" << readyCount.load() << \" threads synchronized\\n\";\n  }\n\n  // Example 2: Using count_down separately from wait\n  std::cout << \"\\nExample 2: Separate count_down and wait\\n\";\n  {\n    constexpr int kNumWorkers = 3;\n    dispenso::Latch workComplete(kNumWorkers);\n    std::vector<int> results(kNumWorkers, 0);\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    // Launch workers\n    for (int i = 0; i < kNumWorkers; ++i) {\n      taskSet.schedule([&workComplete, &results, i]() {\n        // Do work\n        results[static_cast<size_t>(i)] = (i + 1) * 10;\n\n        // Signal work is done (non-blocking)\n        workComplete.count_down();\n      });\n    }\n\n    // Main thread waits for all workers\n    workComplete.wait();\n\n    std::cout << \"  Results: \";\n    for (int r : results) {\n      std::cout << r << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 3: try_wait for non-blocking check\n  std::cout << \"\\nExample 3: Non-blocking try_wait check\\n\";\n  {\n    dispenso::Latch latch(1);\n\n    std::cout << \"  Before count_down, try_wait() = \" << (latch.try_wait() ? \"true\" : \"false\")\n              << \"\\n\";\n\n    latch.count_down();\n\n    std::cout << \"  After count_down, try_wait() = \" << (latch.try_wait() ? \"true\" : \"false\")\n              << \"\\n\";\n  }\n\n  // Example 4: Latch for phased computation\n  std::cout << \"\\nExample 4: Phased computation with multiple latches\\n\";\n  {\n    constexpr int kNumThreads = 4;\n    dispenso::Latch phase1Complete(kNumThreads);\n    dispenso::Latch phase2Complete(kNumThreads);\n\n    std::atomic<int> phase1Sum(0);\n    std::atomic<int> phase2Sum(0);\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    for (int i = 0; i < kNumThreads; ++i) {\n      taskSet.schedule([&, i]() {\n        // Phase 1: Each thread contributes its value\n        phase1Sum.fetch_add(i + 1, std::memory_order_relaxed);\n        phase1Complete.arrive_and_wait();\n\n        // Phase 2: Each thread reads the phase 1 result\n        int localResult = phase1Sum.load() * (i + 1);\n        phase2Sum.fetch_add(localResult, std::memory_order_relaxed);\n        phase2Complete.count_down();\n      });\n    }\n\n    phase2Complete.wait();\n\n    std::cout << \"  Phase 1 sum: \" << phase1Sum.load() << \" (1+2+3+4 = 10)\\n\";\n    std::cout << \"  Phase 2 sum: \" << phase2Sum.load() << \" (10*1 + 10*2 + 10*3 + 10*4 = 100)\\n\";\n  }\n\n  // Example 5: Latch as a one-shot gate\n  std::cout << \"\\nExample 5: Latch as a one-shot start gate\\n\";\n  {\n    dispenso::Latch startGate(1);\n    std::atomic<int> workersStarted(0);\n\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    // Schedule workers that wait for the start signal\n    for (int i = 0; i < 5; ++i) {\n      taskSet.schedule([&startGate, &workersStarted]() {\n        // Wait for start signal\n        startGate.wait();\n        workersStarted.fetch_add(1, std::memory_order_relaxed);\n      });\n    }\n\n    // Let workers queue up\n    std::this_thread::sleep_for(std::chrono::milliseconds(10));\n    std::cout << \"  Workers before gate opens: \" << workersStarted.load() << \"\\n\";\n\n    // Open the gate\n    startGate.count_down();\n\n    taskSet.wait();\n    std::cout << \"  Workers after gate opens: \" << workersStarted.load() << \"\\n\";\n  }\n\n  std::cout << \"\\nAll Latch examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/parallel_for_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example parallel_for_example.cpp\n * Demonstrates basic usage of dispenso::parallel_for for parallel loop execution.\n */\n\n#include <dispenso/parallel_for.h>\n\n#include <cmath>\n#include <iostream>\n#include <vector>\n\nint main() {\n  constexpr size_t kArraySize = 1000000;\n\n  // Create input and output vectors\n  std::vector<double> input(kArraySize);\n  std::vector<double> output(kArraySize);\n\n  // Initialize input data\n  for (size_t i = 0; i < kArraySize; ++i) {\n    input[i] = static_cast<double>(i);\n  }\n\n  // Example 1: Simple parallel_for with index-based lambda\n  // Process each element independently in parallel\n  std::cout << \"Example 1: Simple parallel_for with per-element lambda\\n\";\n  dispenso::parallel_for(0, kArraySize, [&](size_t i) { output[i] = std::sqrt(input[i]); });\n\n  std::cout << \"  output[0] = \" << output[0] << \", output[999999] = \" << output[999999] << \"\\n\";\n\n  // Example 2: parallel_for with range-based lambda for better cache utilization\n  // The lambda receives start and end indices for a chunk (automatic chunking)\n  std::cout << \"\\nExample 2: parallel_for with range-based lambda (chunked)\\n\";\n  dispenso::parallel_for(size_t{0}, kArraySize, [&](size_t start, size_t end) {\n    for (size_t i = start; i < end; ++i) {\n      output[i] = input[i] * 2.0;\n    }\n  });\n\n  std::cout << \"  output[0] = \" << output[0] << \", output[999999] = \" << output[999999] << \"\\n\";\n\n  // Example 3: parallel_for with per-thread state\n  // Useful for reduction operations or when threads need local accumulators\n  std::cout << \"\\nExample 3: parallel_for with per-thread state (reduction)\\n\";\n  std::vector<double> partialSums;\n  dispenso::parallel_for(\n      partialSums,\n      []() { return 0.0; }, // State initializer\n      size_t{0},\n      kArraySize,\n      [&](double& localSum, size_t start, size_t end) {\n        for (size_t i = start; i < end; ++i) {\n          localSum += input[i];\n        }\n      });\n\n  // Combine partial sums\n  double totalSum = 0.0;\n  for (double partial : partialSums) {\n    totalSum += partial;\n  }\n  std::cout << \"  Sum of all elements: \" << totalSum << \"\\n\";\n\n  // Example 4: parallel_for with options to limit parallelism\n  std::cout << \"\\nExample 4: parallel_for with limited parallelism\\n\";\n  dispenso::ParForOptions options;\n  options.maxThreads = 2; // Limit to 2 threads\n  dispenso::parallel_for(\n      0,\n      100,\n      [](size_t i) {\n        // Light work that doesn't need many threads\n        (void)i;\n      },\n      options);\n  std::cout << \"  Completed with maxThreads = 2\\n\";\n\n  std::cout << \"\\nAll parallel_for examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/pipeline_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example pipeline_example.cpp\n * Demonstrates multi-stage pipeline processing with dispenso::pipeline.\n */\n\n#include <dispenso/pipeline.h>\n\n#include <cmath>\n#include <iostream>\n#include <sstream>\n#include <vector>\n\nint main() {\n  // Example 1: Simple 3-stage pipeline (generator -> transform -> sink)\n  std::cout << \"Example 1: Simple 3-stage pipeline\\n\";\n  {\n    std::vector<int> results;\n    int counter = 0;\n\n    dispenso::pipeline(\n        // Stage 1: Generator - produces values\n        [&counter]() -> dispenso::OpResult<int> {\n          if (counter >= 10) {\n            return {}; // Empty result signals end of input\n          }\n          return counter++;\n        },\n        // Stage 2: Transform - squares the value\n        [](int value) { return value * value; },\n        // Stage 3: Sink - collects results\n        [&results](int value) { results.push_back(value); });\n\n    std::cout << \"  Squared values: \";\n    for (int r : results) {\n      std::cout << r << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 2: Pipeline with parallel stages\n  std::cout << \"\\nExample 2: Pipeline with parallel transform stage\\n\";\n  {\n    std::vector<double> results;\n    int counter = 0;\n\n    dispenso::pipeline(\n        // Generator (serial)\n        [&counter]() -> dispenso::OpResult<int> {\n          if (counter >= 100) {\n            return {};\n          }\n          return counter++;\n        },\n        // Transform (parallel with limit of 4 concurrent operations)\n        dispenso::stage(\n            [](int value) {\n              // Simulate expensive computation\n              return std::sqrt(static_cast<double>(value));\n            },\n            4),\n        // Sink (serial)\n        [&results](double value) { results.push_back(value); });\n\n    std::cout << \"  First 5 sqrt results: \";\n    for (size_t i = 0; i < 5 && i < results.size(); ++i) {\n      std::cout << results[i] << \" \";\n    }\n    std::cout << \"...\\n\";\n    std::cout << \"  Total results: \" << results.size() << \"\\n\";\n  }\n\n  // Example 3: Pipeline with filtering\n  std::cout << \"\\nExample 3: Pipeline with filtering (keep only even numbers)\\n\";\n  {\n    std::vector<int> results;\n    int counter = 0;\n\n    dispenso::pipeline(\n        // Generator\n        [&counter]() -> dispenso::OpResult<int> {\n          if (counter >= 20) {\n            return {};\n          }\n          return counter++;\n        },\n        // Filter: only pass through even numbers\n        [](int value) -> dispenso::OpResult<int> {\n          if (value % 2 == 0) {\n            return value;\n          }\n          return {}; // Filter out odd numbers\n        },\n        // Sink\n        [&results](int value) { results.push_back(value); });\n\n    std::cout << \"  Even numbers: \";\n    for (int r : results) {\n      std::cout << r << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 4: Pipeline with type transformation\n  std::cout << \"\\nExample 4: Pipeline with type transformations\\n\";\n  {\n    std::vector<std::string> results;\n    int counter = 0;\n\n    dispenso::pipeline(\n        // Generate integers\n        [&counter]() -> dispenso::OpResult<int> {\n          if (counter >= 5) {\n            return {};\n          }\n          return counter++;\n        },\n        // Transform to double\n        [](int value) { return static_cast<double>(value) * 1.5; },\n        // Transform to string\n        [](double value) {\n          std::ostringstream oss;\n          oss << \"Value: \" << value;\n          return oss.str();\n        },\n        // Collect strings\n        [&results](std::string value) { results.push_back(std::move(value)); });\n\n    std::cout << \"  String results:\\n\";\n    for (const auto& r : results) {\n      std::cout << \"    \" << r << \"\\n\";\n    }\n  }\n\n  // Example 5: Pipeline with custom thread pool\n  std::cout << \"\\nExample 5: Pipeline with custom ThreadPool\\n\";\n  {\n    dispenso::ThreadPool customPool(2);\n    std::vector<int> results;\n    int counter = 0;\n\n    dispenso::pipeline(\n        customPool,\n        // Generator\n        [&counter]() -> dispenso::OpResult<int> {\n          if (counter >= 10) {\n            return {};\n          }\n          return counter++;\n        },\n        // Parallel transform\n        dispenso::stage([](int value) { return value + 100; }, dispenso::kStageNoLimit),\n        // Sink\n        [&results](int value) { results.push_back(value); });\n\n    std::cout << \"  Results from custom pool: \";\n    for (int r : results) {\n      std::cout << r << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 6: Single-stage pipeline (just a generator loop)\n  std::cout << \"\\nExample 6: Single-stage pipeline\\n\";\n  {\n    int sum = 0;\n    int counter = 0;\n\n    // Single stage that returns bool (true = continue, false = stop)\n    dispenso::pipeline([&]() -> bool {\n      if (counter >= 10) {\n        return false;\n      }\n      sum += counter++;\n      return true;\n    });\n\n    std::cout << \"  Sum computed in single stage: \" << sum << \" (expected: 45)\\n\";\n  }\n\n  std::cout << \"\\nAll Pipeline examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/resource_pool_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example resource_pool_example.cpp\n * Demonstrates managing pooled resources with dispenso::ResourcePool.\n */\n\n#include <dispenso/parallel_for.h>\n#include <dispenso/resource_pool.h>\n\n#include <atomic>\n#include <iostream>\n#include <sstream>\n\n// Example resource class - a reusable buffer\nclass Buffer {\n public:\n  Buffer() : data_(1024, 0), useCount_(0) {}\n\n  void process(int value) {\n    // Simulate using the buffer\n    for (size_t i = 0; i < data_.size(); ++i) {\n      data_[i] = value + static_cast<int>(i);\n    }\n    useCount_++;\n  }\n\n  int checksum() const {\n    int sum = 0;\n    for (int val : data_) {\n      sum += val;\n    }\n    return sum;\n  }\n\n  int useCount() const {\n    return useCount_;\n  }\n\n private:\n  std::vector<int> data_;\n  int useCount_;\n};\n\n// Example expensive-to-create resource\nclass DatabaseConnection {\n public:\n  DatabaseConnection(int id) : connectionId_(id), queryCount_(0) {}\n\n  int executeQuery(int param) {\n    queryCount_++;\n    return connectionId_ * 1000 + param;\n  }\n\n  int connectionId() const {\n    return connectionId_;\n  }\n  int queryCount() const {\n    return queryCount_;\n  }\n\n private:\n  int connectionId_;\n  int queryCount_;\n};\n\nint main() {\n  // Example 1: Basic resource pool usage\n  std::cout << \"Example 1: Basic ResourcePool usage\\n\";\n  {\n    // Create a pool of 4 buffers\n    dispenso::ResourcePool<Buffer> bufferPool(4, []() { return Buffer(); });\n\n    std::atomic<int> totalChecksum(0);\n\n    // Use resources from multiple threads\n    dispenso::parallel_for(0, 100, [&bufferPool, &totalChecksum](size_t i) {\n      // Acquire a resource from the pool (blocks if none available)\n      auto resource = bufferPool.acquire();\n\n      // Use the resource\n      resource.get().process(static_cast<int>(i));\n      totalChecksum.fetch_add(resource.get().checksum(), std::memory_order_relaxed);\n\n      // Resource automatically returned to pool when 'resource' goes out of scope\n    });\n\n    std::cout << \"  Total checksum from 100 operations: \" << totalChecksum.load() << \"\\n\";\n  }\n\n  // Example 2: Resource pool with connection-like objects\n  std::cout << \"\\nExample 2: Connection pool pattern\\n\";\n  {\n    std::atomic<int> nextConnectionId(0);\n\n    // Create a pool of 3 \"database connections\"\n    dispenso::ResourcePool<DatabaseConnection> connectionPool(3, [&nextConnectionId]() {\n      return DatabaseConnection(nextConnectionId.fetch_add(1, std::memory_order_relaxed));\n    });\n\n    std::atomic<int> totalResult(0);\n\n    dispenso::parallel_for(0, 50, [&connectionPool, &totalResult](size_t i) {\n      auto conn = connectionPool.acquire();\n      int result = conn.get().executeQuery(static_cast<int>(i));\n      totalResult.fetch_add(result, std::memory_order_relaxed);\n    });\n\n    std::cout << \"  Total query result sum: \" << totalResult.load() << \"\\n\";\n    std::cout << \"  (50 queries distributed across 3 connections)\\n\";\n  }\n\n  // Example 3: Resource pool limiting concurrency\n  std::cout << \"\\nExample 3: Using ResourcePool to limit concurrency\\n\";\n  {\n    // Use a pool of \"permits\" to limit concurrent operations\n    struct Permit {};\n\n    constexpr size_t kMaxConcurrent = 2;\n    dispenso::ResourcePool<Permit> permits(kMaxConcurrent, []() { return Permit(); });\n\n    std::atomic<int> currentActive(0);\n    std::atomic<int> maxObserved(0);\n\n    dispenso::parallel_for(0, 100, [&](size_t i) {\n      // Acquire permit (blocks if max concurrency reached)\n      auto permit = permits.acquire();\n\n      int active = currentActive.fetch_add(1, std::memory_order_relaxed) + 1;\n\n      // Track max concurrent\n      int maxSeen = maxObserved.load(std::memory_order_relaxed);\n      while (active > maxSeen &&\n             !maxObserved.compare_exchange_weak(maxSeen, active, std::memory_order_relaxed)) {\n      }\n\n      // Simulate work\n      volatile int work = 0;\n      for (int j = 0; j < 1000; ++j) {\n        work += j;\n      }\n      (void)work;\n      (void)i;\n\n      currentActive.fetch_sub(1, std::memory_order_relaxed);\n      // Permit returned when scope exits\n    });\n\n    std::cout << \"  Max concurrent operations observed: \" << maxObserved.load() << \" (limit was \"\n              << kMaxConcurrent << \")\\n\";\n  }\n\n  // Example 4: Resource with expensive initialization\n  std::cout << \"\\nExample 4: Resources with expensive initialization\\n\";\n  {\n    std::atomic<int> initCount(0);\n\n    // Each resource is expensive to create, so we pool them\n    dispenso::ResourcePool<std::stringstream> streamPool(2, [&initCount]() {\n      initCount.fetch_add(1, std::memory_order_relaxed);\n      // Simulate expensive setup\n      std::stringstream ss;\n      ss.precision(10);\n      return ss;\n    });\n\n    dispenso::parallel_for(0, 20, [&streamPool](size_t i) {\n      auto stream = streamPool.acquire();\n      stream.get().str(\"\");\n      stream.get() << \"Value: \" << i * 3.14159;\n      // Stream reused, not recreated\n    });\n\n    std::cout << \"  Total initializations: \" << initCount.load() << \" (pool size: 2)\\n\";\n    std::cout << \"  (Only 2 streams were created, reused for 20 operations)\\n\";\n  }\n\n  // Example 5: Nested resource acquisition (be careful with deadlock!)\n  std::cout << \"\\nExample 5: Sequential resource acquisition pattern\\n\";\n  {\n    dispenso::ResourcePool<int> poolA(2, []() { return 100; });\n    dispenso::ResourcePool<int> poolB(2, []() { return 200; });\n\n    std::atomic<int> resultSum(0);\n\n    // Safe pattern: acquire resources sequentially, release in reverse order\n    dispenso::parallel_for(0, 10, [&](size_t i) {\n      auto resA = poolA.acquire();\n      auto resB = poolB.acquire();\n\n      resultSum.fetch_add(resA.get() + resB.get(), std::memory_order_relaxed);\n      (void)i;\n\n      // resB released first, then resA (LIFO order)\n    });\n\n    std::cout << \"  Result sum: \" << resultSum.load() << \" (expected: 3000)\\n\";\n  }\n\n  std::cout << \"\\nAll ResourcePool examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "examples/task_set_example.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * @example task_set_example.cpp\n * Demonstrates scheduling tasks and waiting for completion with TaskSet.\n */\n\n#include <dispenso/task_set.h>\n#include <dispenso/thread_pool.h>\n\n#include <atomic>\n#include <iostream>\n#include <vector>\n\nint main() {\n  // Example 1: Basic TaskSet usage\n  std::cout << \"Example 1: Basic TaskSet with simple tasks\\n\";\n  {\n    dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n    std::atomic<int> counter(0);\n\n    // Schedule several tasks\n    for (int i = 0; i < 10; ++i) {\n      taskSet.schedule([&counter, i]() { counter.fetch_add(i, std::memory_order_relaxed); });\n    }\n\n    // Wait for all tasks to complete\n    taskSet.wait();\n\n    std::cout << \"  Sum of 0..9 = \" << counter.load() << \" (expected: 45)\\n\";\n  }\n\n  // Example 2: ConcurrentTaskSet for multi-threaded scheduling\n  std::cout << \"\\nExample 2: ConcurrentTaskSet (schedule from multiple threads)\\n\";\n  {\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    std::atomic<int> total(0);\n\n    // Schedule tasks that themselves schedule more tasks\n    for (int i = 0; i < 5; ++i) {\n      taskSet.schedule([&taskSet, &total, i]() {\n        // Each task schedules two sub-tasks\n        for (int j = 0; j < 2; ++j) {\n          taskSet.schedule(\n              [&total, i, j]() { total.fetch_add(i * 10 + j, std::memory_order_relaxed); });\n        }\n      });\n    }\n\n    taskSet.wait();\n\n    std::cout << \"  Total from nested scheduling = \" << total.load() << \"\\n\";\n  }\n\n  // Example 3: Using a custom thread pool\n  std::cout << \"\\nExample 3: TaskSet with custom ThreadPool\\n\";\n  {\n    // Create a small thread pool with 2 threads\n    dispenso::ThreadPool customPool(2);\n\n    dispenso::TaskSet taskSet(customPool);\n\n    std::vector<int> results(4, 0);\n\n    for (size_t i = 0; i < results.size(); ++i) {\n      taskSet.schedule([&results, i]() { results[i] = static_cast<int>(i * i); });\n    }\n\n    taskSet.wait();\n\n    std::cout << \"  Squares: \";\n    for (int r : results) {\n      std::cout << r << \" \";\n    }\n    std::cout << \"\\n\";\n  }\n\n  // Example 4: TaskSet cancellation\n  std::cout << \"\\nExample 4: TaskSet cancellation\\n\";\n  {\n    dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n    std::atomic<int> completed(0);\n    std::atomic<int> skipped(0);\n\n    // Schedule many tasks, but cancel after scheduling some\n    for (int i = 0; i < 1000; ++i) {\n      taskSet.schedule([&taskSet, &completed, &skipped]() {\n        if (taskSet.canceled()) {\n          skipped.fetch_add(1, std::memory_order_relaxed);\n          return;\n        }\n        completed.fetch_add(1, std::memory_order_relaxed);\n      });\n\n      // Cancel after scheduling 100 tasks\n      if (i == 100) {\n        taskSet.cancel();\n      }\n    }\n\n    bool wasCanceled = taskSet.wait();\n\n    std::cout << \"  Was canceled: \" << (wasCanceled ? \"yes\" : \"no\") << \"\\n\";\n    std::cout << \"  Completed tasks: \" << completed.load() << \"\\n\";\n    std::cout << \"  Skipped tasks: \" << skipped.load() << \"\\n\";\n  }\n\n  // Example 5: Checking canceled status within tasks\n  std::cout << \"\\nExample 5: Early exit from tasks using canceled()\\n\";\n  {\n    dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n    std::atomic<int> itemsProcessed(0);\n\n    // Schedule a task that processes items and checks for cancellation\n    taskSet.schedule([&taskSet, &itemsProcessed]() {\n      for (int i = 0; i < 1000; ++i) {\n        if (taskSet.canceled()) {\n          // Exit early if canceled\n          break;\n        }\n        itemsProcessed.fetch_add(1, std::memory_order_relaxed);\n      }\n    });\n\n    // Cancel from another task after processing starts\n    taskSet.schedule([&taskSet]() { taskSet.cancel(); });\n\n    taskSet.wait();\n\n    std::cout << \"  Items processed before cancellation: \" << itemsProcessed.load() << \"\\n\";\n  }\n\n  std::cout << \"\\nAll TaskSet examples completed successfully!\\n\";\n  return 0;\n}\n"
  },
  {
    "path": "results/android_arm64.json",
    "content": "{\n  \"machine_info\": {\n    \"timestamp\": \"2026-03-13T21:39:24+00:00\",\n    \"platform\": \"Android\",\n    \"platform_release\": \"12\",\n    \"platform_version\": \"SDK 32\",\n    \"architecture\": \"aarch64\",\n    \"processor\": \"arm64-v8a\",\n    \"device_model\": \"Quest 3\",\n    \"device_name\": \"eureka\",\n    \"soc_manufacturer\": \"Qualcomm\",\n    \"soc_model\": \"SXR2230P\",\n    \"hardware\": \"\",\n    \"cpu_implementer\": \"0x41\",\n    \"cpu_part\": \"0xd4b\",\n    \"cpu_variant\": \"0x0\",\n    \"cpu_cores\": 6,\n    \"cpu_max_freq_mhz\": 2054,\n    \"memory_kb\": 7941372,\n    \"memory_gb\": 7.5,\n    \"kernel\": \"5.10.205-01593-g21f33663a190\",\n    \"platform_id\": \"android-SXR2230P-6c\",\n    \"compiler\": {\n      \"compiler_id\": \"Clang\",\n      \"compiler_version\": \"19.x (Android NDK r26b)\",\n      \"build_type\": \"Release (opt)\",\n      \"compiler_summary\": \"Clang 19.x (Android NDK r26b) Release (opt)\"\n    }\n  },\n  \"results\": [\n    {\n      \"name\": \"cascading_parallel_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:39:28-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./cascading_parallel_for_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24975,\n            \"real_time\": 11202.182462469822,\n            \"cpu_time\": 11180.797637637637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/100000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 274,\n            \"real_time\": 1029693.8759103239,\n            \"cpu_time\": 1025645.7189781022,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/10000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 102025825.99958986,\n            \"cpu_time\": 101746388.00000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1891,\n            \"real_time\": 147090.64674729988,\n            \"cpu_time\": 146669.67001586474,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1885,\n            \"real_time\": 139420.02387293856,\n            \"cpu_time\": 138926.64190981435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1777,\n            \"real_time\": 157708.99437164958,\n            \"cpu_time\": 157105.14124929672,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1605,\n            \"real_time\": 171646.142055542,\n            \"cpu_time\": 170904.6579439254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1506,\n            \"real_time\": 188087.77158036386,\n            \"cpu_time\": 186556.99402390438,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 159,\n            \"real_time\": 1759704.7106895354,\n            \"cpu_time\": 1747337.484276733,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 301,\n            \"real_time\": 925631.1461823646,\n            \"cpu_time\": 921134.9634551505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 385,\n            \"real_time\": 716468.145453421,\n            \"cpu_time\": 712737.4337662347,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 458,\n            \"real_time\": 605852.2707438713,\n            \"cpu_time\": 602639.3078602618,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 492,\n            \"real_time\": 569085.8455289241,\n            \"cpu_time\": 565098.5447154471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 149613010.00039384,\n            \"cpu_time\": 148774817.9999997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 75134707.99995048,\n            \"cpu_time\": 74670859.00000025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 50615046.80015787,\n            \"cpu_time\": 50311843.19999973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 40938315.14260923,\n            \"cpu_time\": 40677708.57142859,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 36961543.85709503,\n            \"cpu_time\": 36640431.14285701,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1842,\n            \"real_time\": 149690.08794803094,\n            \"cpu_time\": 149190.05428881635,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2256,\n            \"real_time\": 124360.79122322708,\n            \"cpu_time\": 123989.0842198585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2211,\n            \"real_time\": 126672.07372210975,\n            \"cpu_time\": 126250.80099502507,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1980,\n            \"real_time\": 141339.5555555142,\n            \"cpu_time\": 140852.2762626264,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1944,\n            \"real_time\": 144893.0879623469,\n            \"cpu_time\": 144090.20267489654,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 1753545.0937543828,\n            \"cpu_time\": 1742947.587499999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 304,\n            \"real_time\": 920307.4506618386,\n            \"cpu_time\": 915574.1249999966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 416,\n            \"real_time\": 674174.120193199,\n            \"cpu_time\": 669940.302884612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 462,\n            \"real_time\": 567108.6428579948,\n            \"cpu_time\": 562437.7640692613,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 570,\n            \"real_time\": 496408.31052544713,\n            \"cpu_time\": 492715.1859649102,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 150388842.99974597,\n            \"cpu_time\": 149007789.99999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 74963484.00036368,\n            \"cpu_time\": 74597360.00000028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 50236367.8333495,\n            \"cpu_time\": 49960087.83333335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 40492846.28568525,\n            \"cpu_time\": 40236972.285714194,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 36228642.874903016,\n            \"cpu_time\": 35834328.62500002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24408,\n            \"real_time\": 11479.564282153204,\n            \"cpu_time\": 11452.482341855173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24648,\n            \"real_time\": 11359.95342418285,\n            \"cpu_time\": 11339.263063940192,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24488,\n            \"real_time\": 11354.091228354944,\n            \"cpu_time\": 11333.014537732819,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24626,\n            \"real_time\": 11362.63826854818,\n            \"cpu_time\": 11337.51770486471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24602,\n            \"real_time\": 11354.038655426712,\n            \"cpu_time\": 11332.960165840203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 266,\n            \"real_time\": 1057726.063909901,\n            \"cpu_time\": 1052840.3195488781,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 381,\n            \"real_time\": 730870.0419976538,\n            \"cpu_time\": 727297.8215223113,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 493,\n            \"real_time\": 548037.2636942863,\n            \"cpu_time\": 545723.3529411742,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 610,\n            \"real_time\": 429752.00655642076,\n            \"cpu_time\": 427672.745901644,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 727,\n            \"real_time\": 407500.9724916474,\n            \"cpu_time\": 405264.20770289056,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 104531659.99994476,\n            \"cpu_time\": 104143920.33333306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 71714668.74979159,\n            \"cpu_time\": 71433165.74999936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 48331223.59996196,\n            \"cpu_time\": 48147426.99999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 41342794.28555082,\n            \"cpu_time\": 41188781.42857138,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 35476186.571551286,\n            \"cpu_time\": 35057246.42857138,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24846,\n            \"real_time\": 11261.29988727075,\n            \"cpu_time\": 11239.353175561382,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20791,\n            \"real_time\": 13471.981386236224,\n            \"cpu_time\": 13434.927372420827,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19998,\n            \"real_time\": 14205.151065086318,\n            \"cpu_time\": 14178.240724072426,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20052,\n            \"real_time\": 14558.53206657101,\n            \"cpu_time\": 14529.449930181525,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20258,\n            \"real_time\": 13972.97655239293,\n            \"cpu_time\": 13878.33428768883,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 272,\n            \"real_time\": 1037306.705878858,\n            \"cpu_time\": 1033160.4264705878,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 408,\n            \"real_time\": 685366.4387260021,\n            \"cpu_time\": 680875.5882352984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 542,\n            \"real_time\": 496504.9889284689,\n            \"cpu_time\": 494506.7416974156,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 690,\n            \"real_time\": 401480.11159571056,\n            \"cpu_time\": 399461.51304347644,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 925,\n            \"real_time\": 320889.6151340309,\n            \"cpu_time\": 317039.64864864876,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 103815080.00015552,\n            \"cpu_time\": 102696077.6666665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 67462584.75004652,\n            \"cpu_time\": 67193516.25000058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 46207417.833102226,\n            \"cpu_time\": 46038352.5000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 38270970.999812044,\n            \"cpu_time\": 38143527.285714336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 34649229.71449726,\n            \"cpu_time\": 34421413.714285724,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"concurrent_vector_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:39:56-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./concurrent_vector_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_std_push_back_serial\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 3072432.769241149,\n            \"cpu_time\": 3057589.3296703296,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_push_back_serial\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 5289420.59617503,\n            \"cpu_time\": 5264596.480769231,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 26558054.69985353,\n            \"cpu_time\": 26441110.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14667761.894758627,\n            \"cpu_time\": 14598944.842105264,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125,\n            \"real_time\": 2245383.9759982657,\n            \"cpu_time\": 2235582.1359999995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 171,\n            \"real_time\": 1641975.6783554412,\n            \"cpu_time\": 1634678.0643274842,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_push_back_serial_reserve\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 1845768.324510693,\n            \"cpu_time\": 1838132.9403973501,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_reserve\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25676702.36368775,\n            \"cpu_time\": 25559034.36363635,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14737101.263132278,\n            \"cpu_time\": 14676946.210526323,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 126,\n            \"real_time\": 2238579.9206353514,\n            \"cpu_time\": 2230051.6825396833,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 174,\n            \"real_time\": 1619006.3907983464,\n            \"cpu_time\": 1611188.063218391,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2033,\n            \"real_time\": 136768.566649875,\n            \"cpu_time\": 136311.72110182003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 263,\n            \"real_time\": 1072412.1787084688,\n            \"cpu_time\": 1068618.5361216723,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 225,\n            \"real_time\": 1246598.2711081677,\n            \"cpu_time\": 1241887.9777777765,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 337,\n            \"real_time\": 833397.4005930811,\n            \"cpu_time\": 831120.4777448096,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate_reverse\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1257,\n            \"real_time\": 223231.17820138438,\n            \"cpu_time\": 222634.7040572789,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate_reverse\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 342,\n            \"real_time\": 821501.9707618625,\n            \"cpu_time\": 819362.3625730982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate_reverse\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77,\n            \"real_time\": 3655440.7142830314,\n            \"cpu_time\": 3647636.6883116905,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate_reverse\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 329,\n            \"real_time\": 854359.2522822755,\n            \"cpu_time\": 850187.6048632221,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_lower_bound\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 79608262.99995461,\n            \"cpu_time\": 79317084.24999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_lower_bound\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 99955079.33308546,\n            \"cpu_time\": 99534099.66666627,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_lower_bound\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 108657354.33314209,\n            \"cpu_time\": 107709340.00000013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_lower_bound\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 74007611.74994841,\n            \"cpu_time\": 73656837.99999978,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_index\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1993,\n            \"real_time\": 136777.56347178397,\n            \"cpu_time\": 136282.06573005498,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_index\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 362,\n            \"real_time\": 775122.2265192381,\n            \"cpu_time\": 772816.5303867421,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_index\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 3691881.5394768133,\n            \"cpu_time\": 3674258.6447368227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_index\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 148,\n            \"real_time\": 1895850.0608204228,\n            \"cpu_time\": 1888489.2297297285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_random\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 4724779.779650616,\n            \"cpu_time\": 4701136.98305084,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_random\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 5496402.788454501,\n            \"cpu_time\": 5470864.403846143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_random\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 6093960.042562685,\n            \"cpu_time\": 6065110.893617047,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_random\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 5669632.860008278,\n            \"cpu_time\": 5642690.560000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 136648068.9994205,\n            \"cpu_time\": 95826839.33333355,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 143536004.00014934,\n            \"cpu_time\": 100548978.99999975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel\",\n            \"family_index\": 33,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 75401752.49960157,\n            \"cpu_time\": 75116082.7499997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel\",\n            \"family_index\": 34,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 34231539.83339944,\n            \"cpu_time\": 33915287.166666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_reserve\",\n            \"family_index\": 35,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 134157044.33343005,\n            \"cpu_time\": 93604004.33333342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_reserve\",\n            \"family_index\": 36,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 75114903.25032355,\n            \"cpu_time\": 74945143.74999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_reserve\",\n            \"family_index\": 37,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34488082.8749865,\n            \"cpu_time\": 31061601.375000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_clear\",\n            \"family_index\": 38,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 134396732.33309197,\n            \"cpu_time\": 94807552.33333345,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_clear\",\n            \"family_index\": 39,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 143588399.6667447,\n            \"cpu_time\": 100260116.66666554,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_clear\",\n            \"family_index\": 40,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 72413015.00016561,\n            \"cpu_time\": 71783620.74999978,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_clear\",\n            \"family_index\": 41,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 32486044.88888102,\n            \"cpu_time\": 32319646.000000075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_10\",\n            \"family_index\": 42,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 18439793.500047844,\n            \"cpu_time\": 13212111.772727298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_10\",\n            \"family_index\": 43,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 22642562.57895843,\n            \"cpu_time\": 15222606.26315785,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_10\",\n            \"family_index\": 44,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 9255702.333333222,\n            \"cpu_time\": 9150227.333333306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"family_index\": 45,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 82,\n            \"real_time\": 3593392.1219510944,\n            \"cpu_time\": 3531427.256097569,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_100\",\n            \"family_index\": 46,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131,\n            \"real_time\": 3325676.6259528515,\n            \"cpu_time\": 2165852.305343528,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_100\",\n            \"family_index\": 47,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 10747807.777766462,\n            \"cpu_time\": 6374092.511111071,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_100\",\n            \"family_index\": 48,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 316,\n            \"real_time\": 886992.6044306201,\n            \"cpu_time\": 877448.079113925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"family_index\": 49,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 645,\n            \"real_time\": 432565.53023335675,\n            \"cpu_time\": 428051.37519379874,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_max\",\n            \"family_index\": 50,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 464,\n            \"real_time\": 985640.7004329821,\n            \"cpu_time\": 646022.9267241446,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_max\",\n            \"family_index\": 51,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 6101889.086212082,\n            \"cpu_time\": 5141329.000000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_max\",\n            \"family_index\": 52,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 985,\n            \"real_time\": 283090.6588836664,\n            \"cpu_time\": 281263.4802030468,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"family_index\": 53,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2356,\n            \"real_time\": 118329.2334460896,\n            \"cpu_time\": 117476.59083191797,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_each_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:40:20-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./for_each_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 3.6400160752236843e-07,\n            \"cpu_time\": 3.6499999999956706e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 4.1600105760153383e-07,\n            \"cpu_time\": 3.6500000000216914e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 3.650002327049151e-07,\n            \"cpu_time\": 3.6500000000216914e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 305362,\n            \"real_time\": 909.9793032527018,\n            \"cpu_time\": 907.814115705295,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212005,\n            \"real_time\": 1278.5740430670805,\n            \"cpu_time\": 1276.070054951534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213786,\n            \"real_time\": 1104.874453886845,\n            \"cpu_time\": 1101.9788760723354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 210089,\n            \"real_time\": 1208.859321531916,\n            \"cpu_time\": 1205.3133195931237,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 169699,\n            \"real_time\": 1662.587611011352,\n            \"cpu_time\": 1656.2057348599583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 312,\n            \"real_time\": 899356.8942339781,\n            \"cpu_time\": 895391.804487181,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 464,\n            \"real_time\": 604533.1077561498,\n            \"cpu_time\": 602070.3297413803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 683,\n            \"real_time\": 413785.9590039493,\n            \"cpu_time\": 411359.57833089336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 797,\n            \"real_time\": 341192.3312416144,\n            \"cpu_time\": 339886.49184441677,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1121,\n            \"real_time\": 256581.11061489768,\n            \"cpu_time\": 253989.97234611964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 87534383.66632812,\n            \"cpu_time\": 87248836.66666639,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 58416068.40003805,\n            \"cpu_time\": 58186042.79999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 39041313.42850243,\n            \"cpu_time\": 38762797.85714282,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 33879019.66662967,\n            \"cpu_time\": 33725734.44444448,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25401328.272809304,\n            \"cpu_time\": 25188560.909090802,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45481,\n            \"real_time\": 6150.10428529867,\n            \"cpu_time\": 6137.659330269768,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16913,\n            \"real_time\": 16516.506474381313,\n            \"cpu_time\": 16482.889197658566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17928,\n            \"real_time\": 15588.800591252735,\n            \"cpu_time\": 15551.514725568859,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16509,\n            \"real_time\": 16748.795263095326,\n            \"cpu_time\": 16710.91974074749,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15882,\n            \"real_time\": 17642.94723584601,\n            \"cpu_time\": 17569.480921798266,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 6122648.934805234,\n            \"cpu_time\": 6105209.3478261065,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 16782241.2940415,\n            \"cpu_time\": 16748437.76470592,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 16720896.294132486,\n            \"cpu_time\": 16640015.470588287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 16135785.94119377,\n            \"cpu_time\": 16078361.000000035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 16500798.23529642,\n            \"cpu_time\": 16403517.52941182,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 611865999.0006562,\n            \"cpu_time\": 610454684.0000005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1662459645.0001264,\n            \"cpu_time\": 1655781332.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1658312666.000711,\n            \"cpu_time\": 1652619182.9999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1654381362.0010042,\n            \"cpu_time\": 1651618719.9999983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1661199853.000653,\n            \"cpu_time\": 1655234847.9999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34723,\n            \"real_time\": 8002.854016110876,\n            \"cpu_time\": 7989.448060363451,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19996,\n            \"real_time\": 13821.888177566336,\n            \"cpu_time\": 13791.76390278071,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16657,\n            \"real_time\": 16791.0029416874,\n            \"cpu_time\": 16757.13159632569,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17349,\n            \"real_time\": 15866.502046227826,\n            \"cpu_time\": 15825.720329702024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14972,\n            \"real_time\": 18214.411768647333,\n            \"cpu_time\": 18122.711127437873,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 8033067.742819965,\n            \"cpu_time\": 8008691.942857179,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 18143033.000039093,\n            \"cpu_time\": 18102971.866666686,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 17601007.562575433,\n            \"cpu_time\": 17560462.250000075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 17037403.64706284,\n            \"cpu_time\": 16987840.117647078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 16896717.35295954,\n            \"cpu_time\": 16804948.23529427,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104981,\n            \"real_time\": 2665.8799782919,\n            \"cpu_time\": 2659.856783608482,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59197,\n            \"real_time\": 4726.791070493045,\n            \"cpu_time\": 4715.818318495855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51842,\n            \"real_time\": 5366.31389606957,\n            \"cpu_time\": 5347.242969021276,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50618,\n            \"real_time\": 5521.94104865395,\n            \"cpu_time\": 5509.778379232643,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47167,\n            \"real_time\": 6092.973243999766,\n            \"cpu_time\": 6047.021328471201,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103044,\n            \"real_time\": 2715.8142249951875,\n            \"cpu_time\": 2710.8534509529823,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58825,\n            \"real_time\": 4857.855707617169,\n            \"cpu_time\": 4848.101045473827,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51462,\n            \"real_time\": 5454.740410417156,\n            \"cpu_time\": 5441.044518285275,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49642,\n            \"real_time\": 5613.515208891196,\n            \"cpu_time\": 5599.823818540763,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45189,\n            \"real_time\": 6182.183584493816,\n            \"cpu_time\": 6138.634579211684,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_latency_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:40:54-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./for_latency_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 30065489.111115713,\n            \"cpu_time\": 5260.222222222285,\n            \"time_unit\": \"ns\",\n            \"mean\": 2.893518519154265e-08,\n            \"stddev\": 2.5880416411933858e-08\n          },\n          {\n            \"name\": \"BM_tbb/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44767365.66690913,\n            \"cpu_time\": 14424687.5,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.014702039930555558,\n            \"stddev\": 0.0003531361544870617\n          },\n          {\n            \"name\": \"BM_tbb/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 37070648.2501646,\n            \"cpu_time\": 6908248.875000002,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.007004479166666661,\n            \"stddev\": 0.0002805563603589796\n          },\n          {\n            \"name\": \"BM_tbb/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34706748.24984599,\n            \"cpu_time\": 4588411.000000001,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.004636731770833402,\n            \"stddev\": 4.5145328525355346e-05\n          },\n          {\n            \"name\": \"BM_tbb/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 33506884.875123434,\n            \"cpu_time\": 3408971.25,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0034360286458333666,\n            \"stddev\": 4.9276378230865174e-05\n          },\n          {\n            \"name\": \"BM_tbb/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 32804241.624944553,\n            \"cpu_time\": 2652786.375000004,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0027350781249999845,\n            \"stddev\": 0.00046697933512709677\n          },\n          {\n            \"name\": \"BM_dispenso/1/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44590499.33332911,\n            \"cpu_time\": 14386996.500000007,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.014520824652777856,\n            \"stddev\": 0.00012720817743809096\n          },\n          {\n            \"name\": \"BM_dispenso/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 37393657.00000365,\n            \"cpu_time\": 7231779.428571434,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.007320788690476222,\n            \"stddev\": 7.385359172545885e-05\n          },\n          {\n            \"name\": \"BM_dispenso/3/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 35743766.62504619,\n            \"cpu_time\": 5597995.249999994,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005678710937499831,\n            \"stddev\": 0.0015502408808643084\n          },\n          {\n            \"name\": \"BM_dispenso/4/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34446670.12490754,\n            \"cpu_time\": 4332923.499999995,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.004379707031250013,\n            \"stddev\": 0.0010042365910835902\n          },\n          {\n            \"name\": \"BM_dispenso/6/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34135986.50013228,\n            \"cpu_time\": 4038482.625000006,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0040653971354167595,\n            \"stddev\": 0.0004235786027342144\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"future_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:40:58-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./future_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 410,\n            \"real_time\": 685395.1390217933,\n            \"cpu_time\": 678990.8658536585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 5483278.745112543,\n            \"cpu_time\": 5464492.627450981,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 48867235.833313316,\n            \"cpu_time\": 48436355.49999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 518473436.9995567,\n            \"cpu_time\": 96979.00000005255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async hangs on this platform at this tree depth\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async hangs on this platform at this tree depth\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 5040517.607150312,\n            \"cpu_time\": 18101.73214285877,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 42016983.285585806,\n            \"cpu_time\": 32894.285714306956,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 336012690.0006435,\n            \"cpu_time\": 127966.99999984007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321,\n            \"real_time\": 864298.1775719081,\n            \"cpu_time\": 37966.84423675998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 6090607.840881355,\n            \"cpu_time\": 286421.52272727195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 49559015.4283231,\n            \"cpu_time\": 2723980.8571428396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 485,\n            \"real_time\": 578304.3958742672,\n            \"cpu_time\": 576677.7195876285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 4553998.2741707545,\n            \"cpu_time\": 4538901.177419354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 36112145.62511122,\n            \"cpu_time\": 35998678.625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 492,\n            \"real_time\": 569903.0894325783,\n            \"cpu_time\": 565229.6036585373,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 4498795.806431454,\n            \"cpu_time\": 4481859.112903227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 35381546.50004799,\n            \"cpu_time\": 34744948.37500003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 2022280.929995759,\n            \"cpu_time\": 115326.09000000083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14852545.315749777,\n            \"cpu_time\": 503042.7894736739,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 125996678.99939959,\n            \"cpu_time\": 39531.00000009257,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:41:05-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./graph_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_taskflow_build_big_tree\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_build_big_tree\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 23287857.454554547,\n            \"cpu_time\": 23076406.818181816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 4741128.661037893,\n            \"cpu_time\": 4714095.118644068,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 5852130.562516321,\n            \"cpu_time\": 5819251.291666665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_chain\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_chain\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2328,\n            \"real_time\": 120323.65335046638,\n            \"cpu_time\": 119976.84450171824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_group\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_group\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 206681,\n            \"real_time\": 1363.148034890439,\n            \"cpu_time\": 1360.1393016290815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11294,\n            \"real_time\": 24804.563219368763,\n            \"cpu_time\": 24756.04223481494,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10841,\n            \"real_time\": 25884.07397837702,\n            \"cpu_time\": 25786.828060142052,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21672,\n            \"real_time\": 13032.079503526009,\n            \"cpu_time\": 13009.694029162067,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21320,\n            \"real_time\": 12996.761960635667,\n            \"cpu_time\": 12956.547701688558,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 5547313.647077638,\n            \"cpu_time\": 5518452.784313763,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 5575856.470671829,\n            \"cpu_time\": 5549767.098039246,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_scene_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:41:09-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./graph_scene_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 78663150.3336442,\n            \"cpu_time\": 78039897.33333336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 46913294.33323214,\n            \"cpu_time\": 46490460.16666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_taskflow/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 47062964.83315479,\n            \"cpu_time\": 61857.83333330826,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 257,\n            \"real_time\": 1092137.1517884014,\n            \"cpu_time\": 1073721.840466922,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"idle_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:41:12-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./idle_pool_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3239,\n            \"real_time\": 86.42811145395417,\n            \"cpu_time\": 86.19453905526397,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1023,\n            \"real_time\": 363.28877028350274,\n            \"cpu_time\": 362.1897399804496,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1052,\n            \"real_time\": 262.9761530415255,\n            \"cpu_time\": 262.46885266159694,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1048,\n            \"real_time\": 264.7457232821323,\n            \"cpu_time\": 264.32237595419844,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 974,\n            \"real_time\": 277.6129106769637,\n            \"cpu_time\": 276.2974681724846,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 325,\n            \"real_time\": 863.6351815389039,\n            \"cpu_time\": 861.2594523076915,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 2800.4709999975926,\n            \"cpu_time\": 2784.616974683547,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 2671.878269228938,\n            \"cpu_time\": 2665.493875000001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 2657.755219046348,\n            \"cpu_time\": 2650.2653428571452,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 2758.0932211409304,\n            \"cpu_time\": 2717.7376346153837,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 86042.94266660872,\n            \"cpu_time\": 85882.77600000006,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 348001.9100006757,\n            \"cpu_time\": 347313.341,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 263200.18300066295,\n            \"cpu_time\": 262644.844,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 267316.64200087835,\n            \"cpu_time\": 266661.98299999966,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 275950.7569990092,\n            \"cpu_time\": 275330.1610000003,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100073.41266646108,\n            \"cpu_time\": 13.923333333387689,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100091.78066684399,\n            \"cpu_time\": 25.746333333150535,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100088.4823333763,\n            \"cpu_time\": 22.135666666756038,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100109.03766669799,\n            \"cpu_time\": 33.80199999991618,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100089.45433340462,\n            \"cpu_time\": 30.36466666668976,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53870,\n            \"real_time\": 5.388512047507226,\n            \"cpu_time\": 5.3775156487840965,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50145,\n            \"real_time\": 5.374452108898085,\n            \"cpu_time\": 5.3605347093429145,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45023,\n            \"real_time\": 6.202122315257175,\n            \"cpu_time\": 6.190225040534833,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 21.59938240001793,\n            \"cpu_time\": 21.552447899999994,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 880,\n            \"real_time\": 250.70977954493918,\n            \"cpu_time\": 249.14388409090975,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9374,\n            \"real_time\": 29.967821740861904,\n            \"cpu_time\": 29.90330691273739,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9531,\n            \"real_time\": 29.369898961096787,\n            \"cpu_time\": 29.309856992970335,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9654,\n            \"real_time\": 30.019263103390394,\n            \"cpu_time\": 29.95850196809607,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6857,\n            \"real_time\": 40.114500802134486,\n            \"cpu_time\": 40.023540032084,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 742,\n            \"real_time\": 403.68798921687477,\n            \"cpu_time\": 400.2272048517511,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109,\n            \"real_time\": 2534.003504579315,\n            \"cpu_time\": 2527.014532110097,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 2567.7155625122136,\n            \"cpu_time\": 2562.3329910714315,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 2501.058044236316,\n            \"cpu_time\": 2495.55912389381,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111,\n            \"real_time\": 2490.3746846715107,\n            \"cpu_time\": 2482.0763693693784,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 3068.1916428615555,\n            \"cpu_time\": 3050.9703571428677,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100065.32266622041,\n            \"cpu_time\": 6.806000000025847,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100077.6663331635,\n            \"cpu_time\": 18.715000000095,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100077.85699963279,\n            \"cpu_time\": 19.13166666689392,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100074.0899999073,\n            \"cpu_time\": 15.485999999971986,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100078.62100004179,\n            \"cpu_time\": 15.850666666613241,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"locality_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:41:25-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./locality_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 214,\n            \"real_time\": 1308224.182241383,\n            \"cpu_time\": 1304595.7056074766,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 52788786.400196835,\n            \"cpu_time\": 52611031.000000015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 422770146.00040275,\n            \"cpu_time\": 421395738.9999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 183,\n            \"real_time\": 1531059.7486287937,\n            \"cpu_time\": 1525012.797814207,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 492,\n            \"real_time\": 592366.9939032308,\n            \"cpu_time\": 587963.223577236,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 332,\n            \"real_time\": 863157.0873499679,\n            \"cpu_time\": 838836.620481927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 4771257.6274623675,\n            \"cpu_time\": 3233403.0784313753,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 8007173.833347123,\n            \"cpu_time\": 4019117.0833333316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 55392414.25003638,\n            \"cpu_time\": 54989961.00000009,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 21749720.08333498,\n            \"cpu_time\": 21512820.583333332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 26127320.299929123,\n            \"cpu_time\": 24236187.900000017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 53764961.83331862,\n            \"cpu_time\": 38943227.4999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 81298966.5000714,\n            \"cpu_time\": 50339869.00000009,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 459815827.00005674,\n            \"cpu_time\": 457028957.9999995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 153945093.49971485,\n            \"cpu_time\": 152642030.50000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 177028611.00042355,\n            \"cpu_time\": 157422314.49999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 274840861.00048447,\n            \"cpu_time\": 229949894.99999985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 362659202.9995663,\n            \"cpu_time\": 210648271.00000018,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 214,\n            \"real_time\": 1307148.6915816134,\n            \"cpu_time\": 1303400.9859813123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 699,\n            \"real_time\": 390006.14878528926,\n            \"cpu_time\": 388336.1745350513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 658,\n            \"real_time\": 356044.3936150428,\n            \"cpu_time\": 284665.8343465035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 1996112.846779485,\n            \"cpu_time\": 601604.9274193557,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55,\n            \"real_time\": 6121975.054570198,\n            \"cpu_time\": 1156185.7272727203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 54404838.80011016,\n            \"cpu_time\": 54035114.799999915,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 19081154.66661305,\n            \"cpu_time\": 18933343.733333293,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 20672425.923084326,\n            \"cpu_time\": 15021049.07692306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25814794.272677813,\n            \"cpu_time\": 7221671.454545422,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 32391594.666680448,\n            \"cpu_time\": 3032813.6666667326,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 424796084.00026333,\n            \"cpu_time\": 422747402.9999989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 155418166.49965766,\n            \"cpu_time\": 153172002.49999985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 157455667.0002494,\n            \"cpu_time\": 59417577.999999695,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 160290537.00003713,\n            \"cpu_time\": 11758129.500000436,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 169323480.49977008,\n            \"cpu_time\": 11761778.000000333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 207,\n            \"real_time\": 1351112.7536304593,\n            \"cpu_time\": 1346793.2415458977,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 793,\n            \"real_time\": 365026.70239557186,\n            \"cpu_time\": 363462.18915510585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 547,\n            \"real_time\": 551542.7495414589,\n            \"cpu_time\": 414834.6252285178,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125,\n            \"real_time\": 2004376.8640025519,\n            \"cpu_time\": 528233.0320000028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 7441747.191517199,\n            \"cpu_time\": 1298321.3829787239,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 54312310.250224985,\n            \"cpu_time\": 54088632.999999665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 19111224.13330304,\n            \"cpu_time\": 18976916.533333346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 21933038.999962334,\n            \"cpu_time\": 16853161.076923173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 26438269.727309074,\n            \"cpu_time\": 1439123.5454544409,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34562191.00007729,\n            \"cpu_time\": 2489384.7500000456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 426584626.0004764,\n            \"cpu_time\": 425353244.00000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 150174259.99940315,\n            \"cpu_time\": 149419948.00000024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 155882906.49975532,\n            \"cpu_time\": 65575187.99999862,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 162923011.0002027,\n            \"cpu_time\": 1795492.4999994403,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 174092256.99975652,\n            \"cpu_time\": 11408391.000001572,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:47:54-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./nested_for_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49415,\n            \"real_time\": 5679.4564403652275,\n            \"cpu_time\": 5664.692522513408,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 166791057.99994433,\n            \"cpu_time\": 166454743.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4840436002.999923,\n            \"cpu_time\": 4831283560.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2168,\n            \"real_time\": 126296.64252772507,\n            \"cpu_time\": 125918.14345018448,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2663,\n            \"real_time\": 104807.28426580124,\n            \"cpu_time\": 104467.60458129931,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2630,\n            \"real_time\": 109019.39847882054,\n            \"cpu_time\": 108657.45665399257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2447,\n            \"real_time\": 115444.83776039345,\n            \"cpu_time\": 115018.9820187987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2318,\n            \"real_time\": 122594.53968947381,\n            \"cpu_time\": 122113.93313201031,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 170237959.49990016,\n            \"cpu_time\": 169849814.50000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 83094608.9996966,\n            \"cpu_time\": 82900382.33333342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 52809640.59966209,\n            \"cpu_time\": 52665323.799999796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 40248849.49982758,\n            \"cpu_time\": 40125928.99999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 26339551.222311758,\n            \"cpu_time\": 26244092.00000007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4813509749.9998665,\n            \"cpu_time\": 4802596013.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2407204145.9985485,\n            \"cpu_time\": 2402930222.9999986,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1606369535.00034,\n            \"cpu_time\": 1603759279.000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1254140176.999499,\n            \"cpu_time\": 1251263637.9999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 852626334.9995134,\n            \"cpu_time\": 848322817.9999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44099,\n            \"real_time\": 6343.2366493602185,\n            \"cpu_time\": 6331.867026463212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65121,\n            \"real_time\": 4289.370571703738,\n            \"cpu_time\": 4281.205939712203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70080,\n            \"real_time\": 3656.074971468738,\n            \"cpu_time\": 3648.2636843607816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84428,\n            \"real_time\": 3317.115459337133,\n            \"cpu_time\": 3308.6310347278154,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87592,\n            \"real_time\": 3217.950806010761,\n            \"cpu_time\": 3200.2358662891534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 166220068.5004791,\n            \"cpu_time\": 165904007.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 81883931.66650106,\n            \"cpu_time\": 81730574.00000043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 52152640.5998884,\n            \"cpu_time\": 52047218.80000136,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 40874205.49997963,\n            \"cpu_time\": 40782525.83333253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 27851096.624999627,\n            \"cpu_time\": 27785260.499999963,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4815991470.000881,\n            \"cpu_time\": 4801187072.999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2404516853.9996667,\n            \"cpu_time\": 2397676666.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1666806416.0003269,\n            \"cpu_time\": 1663118652.9999979,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1386478680.0004368,\n            \"cpu_time\": 1383293456.000004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 941762021.0006135,\n            \"cpu_time\": 937784375.9999962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43115,\n            \"real_time\": 6487.0701148304315,\n            \"cpu_time\": 6473.554169082821,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66342,\n            \"real_time\": 4199.249193552613,\n            \"cpu_time\": 4191.411534171482,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74538,\n            \"real_time\": 3635.251147068784,\n            \"cpu_time\": 3627.658871984722,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85823,\n            \"real_time\": 3261.6344919148632,\n            \"cpu_time\": 3254.352958997046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85933,\n            \"real_time\": 3210.4350947798885,\n            \"cpu_time\": 3200.652519986548,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 167076605.49946013,\n            \"cpu_time\": 166780230.50000235,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 83318532.66645339,\n            \"cpu_time\": 83148522.66666624,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 53096421.99972586,\n            \"cpu_time\": 52981478.19999883,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 38782052.49990667,\n            \"cpu_time\": 38689001.33333142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 25273115.888921894,\n            \"cpu_time\": 25204491.222221274,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4832670011.999653,\n            \"cpu_time\": 4823280844.00001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2443111025.0006895,\n            \"cpu_time\": 2438376755.9999967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1742059964.9994984,\n            \"cpu_time\": 1737795876.9999964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1274559449.9992876,\n            \"cpu_time\": 1271538434.9999964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 868963368.0005499,\n            \"cpu_time\": 865283129.9999945,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:41:52-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./nested_pool_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 3052.7143626386533,\n            \"cpu_time\": 3039.357758241758,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 162,\n            \"real_time\": 1725.198216050041,\n            \"cpu_time\": 1720.0363395061731,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 1311.0043849811634,\n            \"cpu_time\": 1307.673638497652,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 245,\n            \"real_time\": 1139.8819183731187,\n            \"cpu_time\": 1136.8717959183678,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 295,\n            \"real_time\": 980.0156338993258,\n            \"cpu_time\": 976.1214881355927,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 92605.3910000822,\n            \"cpu_time\": 92372.48233333339,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 47964.084666697694,\n            \"cpu_time\": 47849.930833333325,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 34299.93174995616,\n            \"cpu_time\": 34209.51237499998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27905.627799918875,\n            \"cpu_time\": 27825.010500000015,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 21975.713999988027,\n            \"cpu_time\": 21791.684333333338,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 15115136.610000264,\n            \"cpu_time\": 15077652.554999998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7559557.2109996285,\n            \"cpu_time\": 7547521.234000001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5225128.906000463,\n            \"cpu_time\": 5198931.197000001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4189370.2089982983,\n            \"cpu_time\": 4174148.4829999995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2970313.525000165,\n            \"cpu_time\": 2948617.149999997,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 47046.9144999394,\n            \"cpu_time\": 151.5451666674513,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 32721.63522221187,\n            \"cpu_time\": 172.47099999985318,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 26256.294300037553,\n            \"cpu_time\": 165.83360000055336,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 22499.37291662718,\n            \"cpu_time\": 152.43924999985836,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 19685.99892864274,\n            \"cpu_time\": 140.98964285734286,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1363512.9480007892,\n            \"cpu_time\": 1105.0000000025761,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 985011.9729999278,\n            \"cpu_time\": 1129.4780000028481,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 779945.5469994427,\n            \"cpu_time\": 1138.5410000031015,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 747863.5650004435,\n            \"cpu_time\": 1241.3539999940326,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 700121.8929999595,\n            \"cpu_time\": 1378.490000000454,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 311,\n            \"real_time\": 874.2171607743046,\n            \"cpu_time\": 871.6879356913126,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 471,\n            \"real_time\": 593.5836369414889,\n            \"cpu_time\": 592.1705859872579,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 440,\n            \"real_time\": 648.5171113622941,\n            \"cpu_time\": 646.1432386363633,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 472,\n            \"real_time\": 617.9984957617631,\n            \"cpu_time\": 610.8769279661138,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 473,\n            \"real_time\": 507.53605919492,\n            \"cpu_time\": 499.4763276955614,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 26738.820399987162,\n            \"cpu_time\": 26642.281200000183,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 8693.613545498616,\n            \"cpu_time\": 8666.020818181712,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 11112.886519986205,\n            \"cpu_time\": 11087.810719999992,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12384.612999994715,\n            \"cpu_time\": 12336.261999999982,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 14443.582149942813,\n            \"cpu_time\": 14392.684949999788,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4296235.063000495,\n            \"cpu_time\": 4284179.561000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 572158.9629993105,\n            \"cpu_time\": 570953.3700000051,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 687859.5990001486,\n            \"cpu_time\": 686206.987999995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 832972.6869997103,\n            \"cpu_time\": 831183.4410000003,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1237114.3419986765,\n            \"cpu_time\": 1230471.2590000052,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1449,\n            \"real_time\": 193.48733816334627,\n            \"cpu_time\": 192.70786542443216,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 867,\n            \"real_time\": 315.5924117651943,\n            \"cpu_time\": 314.89679930795637,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1175,\n            \"real_time\": 239.9514868088869,\n            \"cpu_time\": 239.63714468084646,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1430,\n            \"real_time\": 198.72244825259818,\n            \"cpu_time\": 198.22821748251343,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1753,\n            \"real_time\": 156.18827609792484,\n            \"cpu_time\": 155.8130176839674,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 5180.161592593154,\n            \"cpu_time\": 5168.7133518519795,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 4850.9469482676905,\n            \"cpu_time\": 4840.643017241271,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 3886.2980704258184,\n            \"cpu_time\": 3877.3313098591893,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90,\n            \"real_time\": 3099.1849222118617,\n            \"cpu_time\": 3078.6348666666972,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 2849.2425673133625,\n            \"cpu_time\": 2839.9018557692284,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 785011.7970010615,\n            \"cpu_time\": 783373.4509999957,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 404659.6230000432,\n            \"cpu_time\": 403821.14400000544,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 319369.9280000146,\n            \"cpu_time\": 317766.57099999994,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 268867.1619998786,\n            \"cpu_time\": 267224.9029999989,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 262039.9740007997,\n            \"cpu_time\": 260119.42099999884,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"once_function_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:42:55-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./once_function_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_move_std_function<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4190784,\n            \"real_time\": 66.94997690153612,\n            \"cpu_time\": 66.79427095264276,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kSmallSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44696078,\n            \"real_time\": 6.280473378439153,\n            \"cpu_time\": 6.266862363180947,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kMediumSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4253905,\n            \"real_time\": 65.9076352199143,\n            \"cpu_time\": 65.76617766499253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kMediumSize>\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45759771,\n            \"real_time\": 6.1327959880093506,\n            \"cpu_time\": 6.120098874620682,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kLargeSize>\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4044690,\n            \"real_time\": 69.33510034138529,\n            \"cpu_time\": 69.17054137647139,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kLargeSize>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44663109,\n            \"real_time\": 6.299513564978442,\n            \"cpu_time\": 6.283911158087983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3308401,\n            \"real_time\": 84.79090654403211,\n            \"cpu_time\": 84.6084235254433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10914074,\n            \"real_time\": 25.703163273476257,\n            \"cpu_time\": 25.653650048552006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200887,\n            \"real_time\": 1392.9191585353794,\n            \"cpu_time\": 1390.198803307332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kSmallSize>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18158,\n            \"real_time\": 15440.894206410487,\n            \"cpu_time\": 15404.594173367108,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kSmallSize>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88361,\n            \"real_time\": 3141.3188963538773,\n            \"cpu_time\": 3134.8513144939557,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91996,\n            \"real_time\": 3046.6177007596016,\n            \"cpu_time\": 3040.4650636984197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kMediumSize>\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9273,\n            \"real_time\": 30537.81559359709,\n            \"cpu_time\": 30458.589345411416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kMediumSize>\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70857,\n            \"real_time\": 3957.286294911814,\n            \"cpu_time\": 3949.142385367715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50962,\n            \"real_time\": 5501.283976281524,\n            \"cpu_time\": 5489.782916683029,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kLargeSize>\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6587,\n            \"real_time\": 42701.67192972245,\n            \"cpu_time\": 42582.92895096402,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kLargeSize>\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50542,\n            \"real_time\": 5558.722151877583,\n            \"cpu_time\": 5541.57510585256,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19796,\n            \"real_time\": 14178.460244519238,\n            \"cpu_time\": 14146.244493837125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2114,\n            \"real_time\": 133131.56717196046,\n            \"cpu_time\": 132627.303216651,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1112,\n            \"real_time\": 256301.4055755807,\n            \"cpu_time\": 254641.08543165404,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pipeline_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:43:04-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./pipeline_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 518612030.99906564,\n            \"cpu_time\": 516453226.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 227088720.00112024,\n            \"cpu_time\": 69128281.99999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 485735985.9997814,\n            \"cpu_time\": 484150431.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 508602915.00066525,\n            \"cpu_time\": 105208.0000001343,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_par/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 106832510.49977116,\n            \"cpu_time\": 252682.49999998993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_par/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 147814415.99916434,\n            \"cpu_time\": 147076641.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow_par/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 506115882.99943835,\n            \"cpu_time\": 89636.00000000405,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pool_allocator_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:43:07-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./pool_allocator_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 3171504.2272770177,\n            \"cpu_time\": 3162807.727272728,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12764288.681782173,\n            \"cpu_time\": 12709531.090909092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1515,\n            \"real_time\": 185259.30033076904,\n            \"cpu_time\": 184801.0184818481,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 743786.1866686338,\n            \"cpu_time\": 741736.3946666669,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3819,\n            \"real_time\": 73305.2055512174,\n            \"cpu_time\": 73139.7962817492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 940,\n            \"real_time\": 293794.134041549,\n            \"cpu_time\": 292808.7904255321,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 11260113.600001205,\n            \"cpu_time\": 11236297.879999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 45310542.666811675,\n            \"cpu_time\": 45167197.66666662,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1515,\n            \"real_time\": 185060.52475269898,\n            \"cpu_time\": 184712.04488448845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 742972.157332891,\n            \"cpu_time\": 741262.4959999997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3829,\n            \"real_time\": 73700.7398799987,\n            \"cpu_time\": 73241.27317837563,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 942,\n            \"real_time\": 294520.71868323715,\n            \"cpu_time\": 293853.3970276008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 11044482.31999413,\n            \"cpu_time\": 11018583.239999983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44925846.499912344,\n            \"cpu_time\": 44750660.16666659,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1516,\n            \"real_time\": 185043.61543511794,\n            \"cpu_time\": 184717.080474934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 376,\n            \"real_time\": 743036.143618117,\n            \"cpu_time\": 741348.3324468075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3824,\n            \"real_time\": 73380.2209730875,\n            \"cpu_time\": 73252.81250000004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 941,\n            \"real_time\": 294322.11583446217,\n            \"cpu_time\": 293699.5260361316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2722,\n            \"real_time\": 102987.60727429499,\n            \"cpu_time\": 102794.26745040425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 673,\n            \"real_time\": 412765.5646364461,\n            \"cpu_time\": 412054.15750371607,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5915,\n            \"real_time\": 47560.18005078068,\n            \"cpu_time\": 47482.87387996624,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1476,\n            \"real_time\": 190938.68360479805,\n            \"cpu_time\": 190588.58062330534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2722,\n            \"real_time\": 102992.08486372787,\n            \"cpu_time\": 102808.67487141798,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 674,\n            \"real_time\": 412837.4243338856,\n            \"cpu_time\": 412062.945103857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5923,\n            \"real_time\": 47479.94698640253,\n            \"cpu_time\": 47398.95407732551,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1467,\n            \"real_time\": 190626.61690568112,\n            \"cpu_time\": 190273.55351056563,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2721,\n            \"real_time\": 102989.20286616778,\n            \"cpu_time\": 102815.59941198141,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 673,\n            \"real_time\": 412740.4918270537,\n            \"cpu_time\": 412033.7295690926,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5887,\n            \"real_time\": 47662.57159827656,\n            \"cpu_time\": 47581.0767793443,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1472,\n            \"real_time\": 193618.04211949557,\n            \"cpu_time\": 190663.39605978315,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 6299882.919993252,\n            \"cpu_time\": 6252269.860000013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 25321330.599945214,\n            \"cpu_time\": 25134610.399999958,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 205,\n            \"real_time\": 1403284.6926810879,\n            \"cpu_time\": 1400613.8341463392,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 5504953.404765512,\n            \"cpu_time\": 5494246.047619024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 21622887.599914975,\n            \"cpu_time\": 21493224.399999987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 80309122.6000106,\n            \"cpu_time\": 79728503.60000017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 203,\n            \"real_time\": 1470129.201972193,\n            \"cpu_time\": 1466372.8768472918,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 5476923.529403946,\n            \"cpu_time\": 5460665.019607851,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 26747051.266769025,\n            \"cpu_time\": 26541226.06666659,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 100668801.60011351,\n            \"cpu_time\": 99942343.59999971,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 1400960.111670872,\n            \"cpu_time\": 1397988.0761421386,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 5937744.0000166735,\n            \"cpu_time\": 5926633.77551022,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 20791680.333382424,\n            \"cpu_time\": 16962845.166666795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 93871224.66675161,\n            \"cpu_time\": 78009708.00000091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 25029213.85712398,\n            \"cpu_time\": 16041575.999999985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 120719413.00018807,\n            \"cpu_time\": 119994816.50000021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 107697367.49989533,\n            \"cpu_time\": 89705214.50000036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 306510603.99941343,\n            \"cpu_time\": 255314039.0000017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 31215094.25000113,\n            \"cpu_time\": 28069374.125000212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 107461886.00023742,\n            \"cpu_time\": 105969514.99999936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 113016521.49995789,\n            \"cpu_time\": 93558516.99999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 532290417.000695,\n            \"cpu_time\": 468213293.0000016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 27231860.444468718,\n            \"cpu_time\": 24027163.333333272,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 125520012.4996918,\n            \"cpu_time\": 122143409.99999961,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 34918624.764673844,\n            \"cpu_time\": 19104540.05882363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 160791669.74986947,\n            \"cpu_time\": 83580013.74999979,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 93409683.74999647,\n            \"cpu_time\": 25095528.375000063,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 353324905.0005907,\n            \"cpu_time\": 221120721.4999984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 153353661.33331263,\n            \"cpu_time\": 85064078.6666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 699948767.0000235,\n            \"cpu_time\": 386371147.9999985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 98188561.7999069,\n            \"cpu_time\": 56965118.40000013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 350214514.33325034,\n            \"cpu_time\": 134577762.33333382,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 170880763.66659757,\n            \"cpu_time\": 114517276.99999975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 740298406.9995,\n            \"cpu_time\": 377159925.00000083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 106705051.11112207,\n            \"cpu_time\": 25232118.88888868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 371980714.0005287,\n            \"cpu_time\": 236069067.00000253,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"rw_lock_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:43:40-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./rw_lock_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 299,\n            \"real_time\": 929544.7558530779,\n            \"cpu_time\": 926329.5986622074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 293,\n            \"real_time\": 934083.3924928682,\n            \"cpu_time\": 929405.8941979525,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 305,\n            \"real_time\": 917672.5639351434,\n            \"cpu_time\": 914784.8426229507,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 300,\n            \"real_time\": 937324.9200022352,\n            \"cpu_time\": 933467.7133333328,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 297,\n            \"real_time\": 936990.6565675302,\n            \"cpu_time\": 933530.4781144779,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44912330.833237015,\n            \"cpu_time\": 44825884.83333338,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44319648.49997409,\n            \"cpu_time\": 44236355.49999997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 43844136.33336711,\n            \"cpu_time\": 43760444.16666665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 43696445.33320146,\n            \"cpu_time\": 43618187.3333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 43647391.49999271,\n            \"cpu_time\": 43569547.99999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14812931.894802636,\n            \"cpu_time\": 14785695.842105282,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13551633.28575838,\n            \"cpu_time\": 13526145.952380933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13201997.85714933,\n            \"cpu_time\": 13178278.523809515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13036749.809543833,\n            \"cpu_time\": 13012802.571428547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12991488.045455215,\n            \"cpu_time\": 12967225.454545468,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 45217851.83351312,\n            \"cpu_time\": 45134670.833333336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 430456606.00000703,\n            \"cpu_time\": 349954019.0000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2176589904.998764,\n            \"cpu_time\": 1122665366.9999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44433893.16656976,\n            \"cpu_time\": 44320226.66666669,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 362874046.9994227,\n            \"cpu_time\": 313894419.9999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1909084409.0005703,\n            \"cpu_time\": 1008395267.9999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 44250785.66691809,\n            \"cpu_time\": 43863610.99999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 361754671.99973357,\n            \"cpu_time\": 335633599.9999995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1422208474.999934,\n            \"cpu_time\": 762341216.0000012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 43780099.833384156,\n            \"cpu_time\": 43617657.83333323,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 417823947.9988406,\n            \"cpu_time\": 408469639.9999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 911962902.9992211,\n            \"cpu_time\": 651650528.0000011,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 43770282.16670927,\n            \"cpu_time\": 43562612.16666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 442135512.9998119,\n            \"cpu_time\": 437615243.9999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 669293295.0008981,\n            \"cpu_time\": 530112638.0000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14808208.68422789,\n            \"cpu_time\": 14766233.473684292,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 187428247.9993781,\n            \"cpu_time\": 186830886.50000012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 887020244.9998033,\n            \"cpu_time\": 884581878.9999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13540147.666693276,\n            \"cpu_time\": 13509821.142857112,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 125367486.50018126,\n            \"cpu_time\": 125092629.5000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 454458952.00100493,\n            \"cpu_time\": 452825635.0000017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13174316.809541086,\n            \"cpu_time\": 13135416.142857097,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 88666536.66700585,\n            \"cpu_time\": 88279511.66666637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 243517941.00039116,\n            \"cpu_time\": 242660211.00000045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12997451.590887398,\n            \"cpu_time\": 12966344.545454623,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 77645372.25011736,\n            \"cpu_time\": 77423268.50000048,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 167798219.9998951,\n            \"cpu_time\": 167007291.50000092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12963905.181839602,\n            \"cpu_time\": 12930229.454545511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 73627051.75000884,\n            \"cpu_time\": 73362889.24999934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 147917020.0000226,\n            \"cpu_time\": 146670441.99999958,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:44:03-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./simple_for_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 3.6400160752236843e-07,\n            \"cpu_time\": 3.650000000004344e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 3.639997885329649e-07,\n            \"cpu_time\": 3.6499999999523025e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000,\n            \"real_time\": 3.650002327049151e-07,\n            \"cpu_time\": 3.120000000578216e-07,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3004,\n            \"real_time\": 91045.54227707216,\n            \"cpu_time\": 90691.11151797607,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3025,\n            \"real_time\": 92005.24330578845,\n            \"cpu_time\": 91705.30280991744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2797,\n            \"real_time\": 100232.79299280152,\n            \"cpu_time\": 99307.38183768328,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2748,\n            \"real_time\": 101569.0491261831,\n            \"cpu_time\": 101109.8005822416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2535,\n            \"real_time\": 109073.37948739853,\n            \"cpu_time\": 108525.10927021696,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 1324021.5539895494,\n            \"cpu_time\": 1309218.3051643183,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 391,\n            \"real_time\": 712905.9462911759,\n            \"cpu_time\": 708361.9718670093,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 527,\n            \"real_time\": 531021.5578755296,\n            \"cpu_time\": 527240.5787476279,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 627,\n            \"real_time\": 450605.52312580135,\n            \"cpu_time\": 446296.44497607683,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 694,\n            \"real_time\": 395989.24783842673,\n            \"cpu_time\": 391635.22334294027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 112580809.66642107,\n            \"cpu_time\": 112137309.66666652,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 56153088.80005614,\n            \"cpu_time\": 55934469.59999983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 37901834.143018015,\n            \"cpu_time\": 37443072.428571254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 29182514.44457888,\n            \"cpu_time\": 28778627.444444522,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25143932.36362428,\n            \"cpu_time\": 24803300.09090908,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 475413.3799997362,\n            \"cpu_time\": 31032.081999999406,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_taskflow/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 487887.13199974154,\n            \"cpu_time\": 30502.58000000028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_taskflow/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 388376.7569986958,\n            \"cpu_time\": 29450.939000000177,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_taskflow/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 339490.451000529,\n            \"cpu_time\": 29897.606000000465,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_taskflow/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 317386.021000857,\n            \"cpu_time\": 28856.431000001237,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_taskflow/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 22203000.870360013,\n            \"cpu_time\": 16215.185185192779,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_taskflow/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 120,\n            \"real_time\": 23582887.766663894,\n            \"cpu_time\": 18940.05833332398,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_taskflow/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 13557144.579990564,\n            \"cpu_time\": 16182.750000002245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_taskflow/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 10253444.769987253,\n            \"cpu_time\": 20453.09999999745,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_taskflow/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 7517060.129994206,\n            \"cpu_time\": 15677.670000009413,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_taskflow/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 152300084.33294037,\n            \"cpu_time\": 18975.333333060007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_taskflow/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 151988021.14303234,\n            \"cpu_time\": 19025.14285718431,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_taskflow/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 156515455.9091091,\n            \"cpu_time\": 18731.272727314583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_taskflow/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 147216677.0001119,\n            \"cpu_time\": 18784.66666660472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_taskflow/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 150376599.16667205,\n            \"cpu_time\": 19284.083333293012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355626,\n            \"real_time\": 784.9189316885689,\n            \"cpu_time\": 782.352811661692,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 357076,\n            \"real_time\": 784.2254898128845,\n            \"cpu_time\": 782.4031662727284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 356517,\n            \"real_time\": 785.0735280539584,\n            \"cpu_time\": 782.9321995865545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 356731,\n            \"real_time\": 786.0184957256699,\n            \"cpu_time\": 783.3469981582773,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 356551,\n            \"real_time\": 785.3296723368471,\n            \"cpu_time\": 782.8977285156972,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 332,\n            \"real_time\": 843640.1114456849,\n            \"cpu_time\": 840483.662650602,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 465,\n            \"real_time\": 600138.8365578067,\n            \"cpu_time\": 596342.612903223,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 672,\n            \"real_time\": 409896.41666740115,\n            \"cpu_time\": 406575.37053571484,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 807,\n            \"real_time\": 331123.7943006877,\n            \"cpu_time\": 329540.6679058253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1046,\n            \"real_time\": 252982.2695995691,\n            \"cpu_time\": 250026.29158699786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 75920489.24971095,\n            \"cpu_time\": 75703059.24999943,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 57270130.600227274,\n            \"cpu_time\": 57110207.20000021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 38690896.71440763,\n            \"cpu_time\": 38540521.428571545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 33102457.750146642,\n            \"cpu_time\": 32979153.874999944,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25235859.5454015,\n            \"cpu_time\": 25057561.727273025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 365582,\n            \"real_time\": 765.0873483959141,\n            \"cpu_time\": 763.4907872925959,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 365334,\n            \"real_time\": 768.0201733220239,\n            \"cpu_time\": 765.467503708939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 365206,\n            \"real_time\": 767.0787090026342,\n            \"cpu_time\": 765.7467648395776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 365081,\n            \"real_time\": 765.3510645568663,\n            \"cpu_time\": 763.5591444090522,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 365639,\n            \"real_time\": 767.6336468497693,\n            \"cpu_time\": 764.1536871066812,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 330,\n            \"real_time\": 839946.4212164853,\n            \"cpu_time\": 835181.0454545473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 463,\n            \"real_time\": 596886.6457874896,\n            \"cpu_time\": 594566.4600431971,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 638,\n            \"real_time\": 408673.71159796545,\n            \"cpu_time\": 406349.51724137674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 783,\n            \"real_time\": 336803.12771398167,\n            \"cpu_time\": 334909.33716475137,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1058,\n            \"real_time\": 250648.55576438655,\n            \"cpu_time\": 248680.6937618168,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 74169616.75016864,\n            \"cpu_time\": 73624403.75000024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 57615349.600018814,\n            \"cpu_time\": 57459270.79999973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 38499698.71407665,\n            \"cpu_time\": 38346317.571428604,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 33196800.12509707,\n            \"cpu_time\": 33066862.374999672,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 24870553.749982115,\n            \"cpu_time\": 24676454.750000093,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355000,\n            \"real_time\": 788.769884508236,\n            \"cpu_time\": 786.8481605633802,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355572,\n            \"real_time\": 787.1853492389914,\n            \"cpu_time\": 785.7495134600032,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355417,\n            \"real_time\": 787.6064622694886,\n            \"cpu_time\": 785.7331528880183,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355785,\n            \"real_time\": 788.9788805014125,\n            \"cpu_time\": 785.5691246117758,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 354445,\n            \"real_time\": 790.0848989303812,\n            \"cpu_time\": 786.7530307946151,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 358,\n            \"real_time\": 784549.6592172775,\n            \"cpu_time\": 780389.0474860348,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 474,\n            \"real_time\": 593804.9999993397,\n            \"cpu_time\": 591202.7573839615,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 700,\n            \"real_time\": 400983.8199999649,\n            \"cpu_time\": 397157.7357142866,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 907,\n            \"real_time\": 306756.7375979173,\n            \"cpu_time\": 305237.337375961,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1244,\n            \"real_time\": 226260.86655957447,\n            \"cpu_time\": 224036.45739549748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 73679629.75013143,\n            \"cpu_time\": 73466275.75000042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 55469255.60011004,\n            \"cpu_time\": 55322447.800000414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 37447106.624995284,\n            \"cpu_time\": 37315879.12499945,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 28672903.899860103,\n            \"cpu_time\": 28540666.199999977,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 24134290.583333496,\n            \"cpu_time\": 23964635.41666627,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:44:53-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./simple_pool_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3104,\n            \"real_time\": 90.03957474230924,\n            \"cpu_time\": 89.854168814433,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 989,\n            \"real_time\": 259.0293478247569,\n            \"cpu_time\": 258.4668372093023,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1060,\n            \"real_time\": 262.4333990563585,\n            \"cpu_time\": 261.7263622641509,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1026,\n            \"real_time\": 273.57316764154865,\n            \"cpu_time\": 272.50842982456135,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1034,\n            \"real_time\": 298.0061547389893,\n            \"cpu_time\": 297.6168607350097,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 305,\n            \"real_time\": 910.0875213155886,\n            \"cpu_time\": 907.1581540983601,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108,\n            \"real_time\": 2630.096231465965,\n            \"cpu_time\": 2623.8666759259277,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 2660.879733334046,\n            \"cpu_time\": 2654.605161904765,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103,\n            \"real_time\": 2662.4582912597707,\n            \"cpu_time\": 2655.268446601943,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 95,\n            \"real_time\": 2860.4586210444963,\n            \"cpu_time\": 2839.104694736839,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 228194.91799964453,\n            \"cpu_time\": 226830.31300000023,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 265269.81800088834,\n            \"cpu_time\": 264591.9760000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 262043.30699874845,\n            \"cpu_time\": 261289.88899999994,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 270964.8700001708,\n            \"cpu_time\": 270231.7709999997,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 307126.74900132697,\n            \"cpu_time\": 305395.30999999976,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 415,\n            \"real_time\": 672.7934915669534,\n            \"cpu_time\": 455.4195783132542,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 462,\n            \"real_time\": 622.4681580112516,\n            \"cpu_time\": 580.3154307359292,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 434,\n            \"real_time\": 652.3204124424674,\n            \"cpu_time\": 620.664463133639,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 411,\n            \"real_time\": 663.499406325511,\n            \"cpu_time\": 628.6836204379567,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 397,\n            \"real_time\": 679.2606675040469,\n            \"cpu_time\": 640.7456901763231,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 6360.496613607128,\n            \"cpu_time\": 4577.662477272729,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 5870.0094468030275,\n            \"cpu_time\": 5750.72495744681,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 6281.448295463964,\n            \"cpu_time\": 6182.935704545453,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 6450.842250036327,\n            \"cpu_time\": 6330.597818181815,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 6499.728116301243,\n            \"cpu_time\": 6404.836604651166,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 642591.6270000016,\n            \"cpu_time\": 434900.1579999996,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 578158.0260008923,\n            \"cpu_time\": 575683.3760000006,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 615674.4370000524,\n            \"cpu_time\": 613544.525,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 631774.0729991783,\n            \"cpu_time\": 629336.1989999991,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 644738.7099997286,\n            \"cpu_time\": 641160.9289999998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10765,\n            \"real_time\": 25.95345415691071,\n            \"cpu_time\": 25.861830376219235,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14734,\n            \"real_time\": 18.872207139982944,\n            \"cpu_time\": 18.835406746301025,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1308,\n            \"real_time\": 223.55017048906728,\n            \"cpu_time\": 222.5209136085637,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 973,\n            \"real_time\": 290.80397533440083,\n            \"cpu_time\": 289.9018838643365,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 664,\n            \"real_time\": 444.4975647583119,\n            \"cpu_time\": 443.26212048192815,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1082,\n            \"real_time\": 258.86781515741933,\n            \"cpu_time\": 258.235717190388,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1798,\n            \"real_time\": 156.22130923273875,\n            \"cpu_time\": 155.84271968854287,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 2019.6027999918442,\n            \"cpu_time\": 2014.9880499999992,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 2928.119788451183,\n            \"cpu_time\": 2914.6865000000066,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61,\n            \"real_time\": 4294.932967211219,\n            \"cpu_time\": 4280.010278688526,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 25882.57354545931,\n            \"cpu_time\": 25834.095181818157,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 30368.695111165936,\n            \"cpu_time\": 30287.528666666694,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 225749.34499971278,\n            \"cpu_time\": 225218.23599999992,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 281113.4650000895,\n            \"cpu_time\": 280501.15199999936,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 423006.24000017706,\n            \"cpu_time\": 421862.4059999989,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71774,\n            \"real_time\": 3.8957624627460876,\n            \"cpu_time\": 3.8890541700337096,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12284,\n            \"real_time\": 20.73410827078801,\n            \"cpu_time\": 20.695764978834216,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2260,\n            \"real_time\": 116.03614734546915,\n            \"cpu_time\": 115.61304159291923,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2369,\n            \"real_time\": 118.67673490973019,\n            \"cpu_time\": 118.45359434360599,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2165,\n            \"real_time\": 140.77349376445852,\n            \"cpu_time\": 140.29491547343983,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7392,\n            \"real_time\": 38.01663068179157,\n            \"cpu_time\": 37.94183482142864,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 672,\n            \"real_time\": 525.5522752972432,\n            \"cpu_time\": 523.4378050595213,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 225,\n            \"real_time\": 1082.700568893213,\n            \"cpu_time\": 1080.2819333333325,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 239,\n            \"real_time\": 1192.9172217617227,\n            \"cpu_time\": 1190.1865606694523,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 230,\n            \"real_time\": 1296.6645304360377,\n            \"cpu_time\": 1293.2292000000111,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 3724.5934266684344,\n            \"cpu_time\": 3717.6035066666677,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 19238.253357018817,\n            \"cpu_time\": 19190.744142857344,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 118575.74099940393,\n            \"cpu_time\": 117834.9764999993,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 118438.63149988465,\n            \"cpu_time\": 118193.0229999999,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 129276.393499822,\n            \"cpu_time\": 128832.70900000099,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"small_buffer_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:45:15-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./small_buffer_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 480,\n            \"real_time\": 584017.6375007407,\n            \"cpu_time\": 582798.8312500002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 2515437.8482251815,\n            \"cpu_time\": 2509441.535714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2661,\n            \"real_time\": 105516.16572744322,\n            \"cpu_time\": 105281.02743329573,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 665,\n            \"real_time\": 421473.33383342664,\n            \"cpu_time\": 420433.42706766917,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 333,\n            \"real_time\": 843822.1891927177,\n            \"cpu_time\": 841412.6606606605,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 3519757.7341667837,\n            \"cpu_time\": 3511068.6708860747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2513,\n            \"real_time\": 112088.35972895606,\n            \"cpu_time\": 111866.93911659381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 626,\n            \"real_time\": 447662.1182107373,\n            \"cpu_time\": 446622.1581469647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 234,\n            \"real_time\": 1198022.0641016474,\n            \"cpu_time\": 1195401.3034188035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57,\n            \"real_time\": 4918945.105249836,\n            \"cpu_time\": 4902126.473684212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2449,\n            \"real_time\": 114935.6353612535,\n            \"cpu_time\": 114399.54389546756,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 613,\n            \"real_time\": 458002.61174738454,\n            \"cpu_time\": 457064.3833605222,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 64,\n            \"real_time\": 304266.9990218627,\n            \"cpu_time\": 3293421.1562500005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 16,\n            \"real_time\": 1650520.7968506853,\n            \"cpu_time\": 14543508.562499989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2192,\n            \"real_time\": 14257.33724899483,\n            \"cpu_time\": 117101.3430656931,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 592,\n            \"real_time\": 67319.2164276847,\n            \"cpu_time\": 488834.38006756845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 48,\n            \"real_time\": 522474.75521246163,\n            \"cpu_time\": 5184009.312499998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 16,\n            \"real_time\": 2673324.847648928,\n            \"cpu_time\": 21659479.374999955,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1872,\n            \"real_time\": 13103.715444592523,\n            \"cpu_time\": 139004.12820512787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 480,\n            \"real_time\": 83240.86666675612,\n            \"cpu_time\": 604080.0895833329,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 48,\n            \"real_time\": 632238.6276001643,\n            \"cpu_time\": 6431436.70833334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 16,\n            \"real_time\": 2408651.7695067753,\n            \"cpu_time\": 19440617.81250001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1648,\n            \"real_time\": 17412.032122255594,\n            \"cpu_time\": 163116.46237864092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 368,\n            \"real_time\": 78231.75781295355,\n            \"cpu_time\": 644890.331521739,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"summing_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:45:20-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./summing_for_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1129160,\n            \"real_time\": 251.80944507283513,\n            \"cpu_time\": 251.27524088703112,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1063,\n            \"real_time\": 263624.59548326954,\n            \"cpu_time\": 262893.2521166511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27690278.79985515,\n            \"cpu_time\": 27627797.3,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3028,\n            \"real_time\": 90270.4190884545,\n            \"cpu_time\": 90004.10766182322,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3102,\n            \"real_time\": 91385.99322991195,\n            \"cpu_time\": 91098.5009671179,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3077,\n            \"real_time\": 90688.41631455503,\n            \"cpu_time\": 90402.22684432876,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2798,\n            \"real_time\": 100682.43566867914,\n            \"cpu_time\": 100276.55575411016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2572,\n            \"real_time\": 108105.93506971282,\n            \"cpu_time\": 107656.47783825822,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 772,\n            \"real_time\": 361091.89766770863,\n            \"cpu_time\": 359372.63860103703,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1254,\n            \"real_time\": 226209.27751286596,\n            \"cpu_time\": 225108.1100478469,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1387,\n            \"real_time\": 197604.07426051615,\n            \"cpu_time\": 196764.48449891884,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1363,\n            \"real_time\": 202477.5891421317,\n            \"cpu_time\": 201509.1239911962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1233,\n            \"real_time\": 222307.40308201284,\n            \"cpu_time\": 220420.71613949756,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27508091.299932856,\n            \"cpu_time\": 27315438.699999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14526300.789408483,\n            \"cpu_time\": 14484062.368421037,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12690290.09092099,\n            \"cpu_time\": 12634953.00000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 13073473.523815794,\n            \"cpu_time\": 13008318.761904748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 13904092.550001225,\n            \"cpu_time\": 13797030.95,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 884126,\n            \"real_time\": 316.497034359714,\n            \"cpu_time\": 315.8163689338406,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 883747,\n            \"real_time\": 315.0814294150636,\n            \"cpu_time\": 314.350609393865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 882127,\n            \"real_time\": 315.71763249400396,\n            \"cpu_time\": 314.91278806793304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 885453,\n            \"real_time\": 316.05906242349005,\n            \"cpu_time\": 315.2931855219875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 881324,\n            \"real_time\": 316.64861844198214,\n            \"cpu_time\": 315.7995447758135,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1054,\n            \"real_time\": 264033.47058854304,\n            \"cpu_time\": 262742.2817836813,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2064,\n            \"real_time\": 135175.76986459055,\n            \"cpu_time\": 134740.69040697673,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2918,\n            \"real_time\": 94069.00651105503,\n            \"cpu_time\": 93754.6919122687,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2959,\n            \"real_time\": 95777.05272045032,\n            \"cpu_time\": 94985.6894221019,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2772,\n            \"real_time\": 100219.8986292068,\n            \"cpu_time\": 99471.57359307355,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 26737148.50006945,\n            \"cpu_time\": 26676838.899999924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14624502.526299022,\n            \"cpu_time\": 14581206.368421031,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12813765.454583602,\n            \"cpu_time\": 12773818.863636356,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 12872484.68179314,\n            \"cpu_time\": 12782050.227272717,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 13727931.050016195,\n            \"cpu_time\": 13279354.100000072,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 890461,\n            \"real_time\": 314.4762432048644,\n            \"cpu_time\": 313.08752545030114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 890615,\n            \"real_time\": 314.19116116507774,\n            \"cpu_time\": 313.42241260252644,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 887337,\n            \"real_time\": 315.02344092548077,\n            \"cpu_time\": 314.07417925771114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 889265,\n            \"real_time\": 313.58373263371317,\n            \"cpu_time\": 312.9672628519087,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 889034,\n            \"real_time\": 314.89571489929745,\n            \"cpu_time\": 314.20474020116217,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1057,\n            \"real_time\": 264797.8524136157,\n            \"cpu_time\": 264070.03784295166,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2068,\n            \"real_time\": 134588.08172106647,\n            \"cpu_time\": 134166.36460348198,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3006,\n            \"real_time\": 96096.9474385472,\n            \"cpu_time\": 95809.26413838958,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3105,\n            \"real_time\": 89297.42930779717,\n            \"cpu_time\": 88980.54170692508,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2961,\n            \"real_time\": 95291.63019264625,\n            \"cpu_time\": 94653.44376899648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27858252.799887847,\n            \"cpu_time\": 27796103.50000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 14813534.894768197,\n            \"cpu_time\": 14782423.263157869,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 13007861.136347027,\n            \"cpu_time\": 12930980.318181831,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 12950212.095217597,\n            \"cpu_time\": 12861391.523809489,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 13891178.450012377,\n            \"cpu_time\": 13586171.90000011,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"timed_task_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:45:42-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./timed_task_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_dispenso<2,false>/manual_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 433.9999999999668,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.3026822916666122e-05,\n            \"stddev\": 9.531265906036618e-06\n          },\n          {\n            \"name\": \"BM_dispenso<4,false>/manual_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 764.0000000000309,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.4833593750000033e-05,\n            \"stddev\": 8.592811971375009e-06\n          },\n          {\n            \"name\": \"BM_dispenso<6,false>/manual_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 555.6666666667783,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.778177083333242e-05,\n            \"stddev\": 1.5400723025035576e-05\n          },\n          {\n            \"name\": \"BM_dispenso<2,true>/manual_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 451.33333333313936,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.957994793744866e-05,\n            \"stddev\": 8.26768700793036e-05\n          },\n          {\n            \"name\": \"BM_dispenso<4,true>/manual_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 764.0000000000309,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.4620833376589697e-05,\n            \"stddev\": 1.2271914481560082e-05\n          },\n          {\n            \"name\": \"BM_dispenso<6,true>/manual_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 572.9999999999509,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.8441666644356137e-05,\n            \"stddev\": 3.579859605078633e-05\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 798.6666666666652,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.613559027778929e-05,\n            \"stddev\": 4.5668162018048904e-05\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 589.9999999999656,\n            \"time_unit\": \"ns\",\n            \"mean\": 1.6044704889427604e-05,\n            \"stddev\": 5.7341844383385104e-05\n          },\n          {\n            \"name\": \"BM_folly<2,false>/manual_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 711.666666666777,\n            \"time_unit\": \"ns\",\n            \"mean\": 7.470572916667035e-05,\n            \"stddev\": 0.00013300534118277458\n          },\n          {\n            \"name\": \"BM_folly<4,false>/manual_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 607.6666666671634,\n            \"time_unit\": \"ns\",\n            \"mean\": 8.356223958333586e-05,\n            \"stddev\": 0.00027005312700179474\n          },\n          {\n            \"name\": \"BM_folly<6,false>/manual_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 573.00000000024,\n            \"time_unit\": \"ns\",\n            \"mean\": 9.574322916667717e-05,\n            \"stddev\": 0.0004091264225462286\n          },\n          {\n            \"name\": \"BM_folly<2,true>/manual_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 468.6666666668902,\n            \"time_unit\": \"ns\",\n            \"mean\": 6.417109385951033e-05,\n            \"stddev\": 9.798314414891915e-06\n          },\n          {\n            \"name\": \"BM_folly<4,true>/manual_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 590.3333333331235,\n            \"time_unit\": \"ns\",\n            \"mean\": 7.66221352865805e-05,\n            \"stddev\": 0.00010170333856705505\n          },\n          {\n            \"name\": \"BM_folly<6,true>/manual_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 624.9999999994685,\n            \"time_unit\": \"ns\",\n            \"mean\": 6.645494789463045e-05,\n            \"stddev\": 9.144976228540142e-06\n          },\n          {\n            \"name\": \"BM_folly_mixed<false>/manual_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 624.9999999994685,\n            \"time_unit\": \"ns\",\n            \"mean\": 7.140833333333728e-05,\n            \"stddev\": 0.0001969415560385558\n          },\n          {\n            \"name\": \"BM_folly_mixed<true>/manual_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 100000000.00000001,\n            \"cpu_time\": 590.3333333337017,\n            \"time_unit\": \"ns\",\n            \"mean\": 6.213472213352564e-05,\n            \"stddev\": 7.071315222038903e-06\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"trivial_compute_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-13T14:46:08-07:00\",\n          \"host_name\": \"localhost\",\n          \"executable\": \"./trivial_compute_benchmark\",\n          \"num_cpus\": 6,\n          \"mhz_per_cpu\": 2054,\n          \"cpu_scaling_enabled\": true,\n          \"caches\": [],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200395,\n            \"real_time\": 1405.29343546074,\n            \"cpu_time\": 1400.357723496095,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 109626069.66677414,\n            \"cpu_time\": 108638559.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1486211970.9996479,\n            \"cpu_time\": 1483235488.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3022,\n            \"real_time\": 89707.3289211519,\n            \"cpu_time\": 89393.93977498348,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3115,\n            \"real_time\": 90376.59711030315,\n            \"cpu_time\": 89864.45040128408,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3098,\n            \"real_time\": 89685.87830816176,\n            \"cpu_time\": 89381.0196901229,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2875,\n            \"real_time\": 96953.10747812747,\n            \"cpu_time\": 96500.23652173909,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2686,\n            \"real_time\": 104725.39985131778,\n            \"cpu_time\": 104241.04988830966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 109009785.33330393,\n            \"cpu_time\": 108779444.33333327,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 54629807.600213096,\n            \"cpu_time\": 54509364.59999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 36805036.25014353,\n            \"cpu_time\": 36689250.99999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27842325.69993037,\n            \"cpu_time\": 27738036.90000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 20210388.928587366,\n            \"cpu_time\": 19925023.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1431572797.9992516,\n            \"cpu_time\": 1428722246.9999995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 716690019.0004526,\n            \"cpu_time\": 715306461.9999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 477958485.00027204,\n            \"cpu_time\": 476956507.0000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 371549829.000287,\n            \"cpu_time\": 370501566.0000015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 251682889.0002216,\n            \"cpu_time\": 250444949.00000203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197650,\n            \"real_time\": 1414.8151024542524,\n            \"cpu_time\": 1412.261548191247,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197741,\n            \"real_time\": 1414.4553178160272,\n            \"cpu_time\": 1411.3342908147665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197691,\n            \"real_time\": 1415.6990758309155,\n            \"cpu_time\": 1412.3785503639374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197706,\n            \"real_time\": 1416.666757713665,\n            \"cpu_time\": 1412.7337359513624,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197987,\n            \"real_time\": 1413.2402885015313,\n            \"cpu_time\": 1410.6879441579547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 108036694.66622524,\n            \"cpu_time\": 107843716.3333336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 54460974.199901104,\n            \"cpu_time\": 54088571.80000055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 36234879.87488261,\n            \"cpu_time\": 36076627.24999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 27627096.499963958,\n            \"cpu_time\": 27556703.900000203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 19139120.46158937,\n            \"cpu_time\": 19053678.15384606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1425677068.9989934,\n            \"cpu_time\": 1421473540.000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 735477416.9998564,\n            \"cpu_time\": 733963126.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 501226352.00023067,\n            \"cpu_time\": 497932131.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 376238369.9995553,\n            \"cpu_time\": 375136934.00000036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 258120546.99963483,\n            \"cpu_time\": 256859327.0000008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197717,\n            \"real_time\": 1417.2270062783748,\n            \"cpu_time\": 1413.3037219864855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197712,\n            \"real_time\": 1416.5708151242143,\n            \"cpu_time\": 1412.7266579671773,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197541,\n            \"real_time\": 1416.6076966381022,\n            \"cpu_time\": 1413.1483945105056,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197462,\n            \"real_time\": 1419.2787523683355,\n            \"cpu_time\": 1414.2581408068638,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197712,\n            \"real_time\": 1417.1184854703952,\n            \"cpu_time\": 1414.320951687301,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 108494889.33369382,\n            \"cpu_time\": 107922812.33333276,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 98328968.00010835,\n            \"cpu_time\": 98125295.33333248,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 64859485.75027578,\n            \"cpu_time\": 64757709.50000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 48806497.99997628,\n            \"cpu_time\": 48682189.16666696,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 32719512.14290831,\n            \"cpu_time\": 32625966.571428325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1425434726.0011854,\n            \"cpu_time\": 1422884594.9999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 758288148.9997817,\n            \"cpu_time\": 756877291.0000021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 541271825.0008765,\n            \"cpu_time\": 540001092.0000043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 462697547.00006163,\n            \"cpu_time\": 459259799.00000155,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 316888936.9990211,\n            \"cpu_time\": 315872140.9999998,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "results/linux_x64.json",
    "content": "{\n  \"machine_info\": {\n    \"timestamp\": \"2026-03-20T07:38:08.196941\",\n    \"platform\": \"Linux\",\n    \"platform_release\": \"6.19.6-100.fc42.x86_64\",\n    \"platform_version\": \"#1 SMP PREEMPT_DYNAMIC Fri Mar  6 17:40:09 UTC 2026\",\n    \"architecture\": \"x86_64\",\n    \"processor\": \"\",\n    \"python_version\": \"3.13.12\",\n    \"cpu_model\": \"AMD Ryzen Threadripper PRO 7995WX 96-Cores\",\n    \"cpu_cores\": 192,\n    \"cache_size\": \"1024 KB\",\n    \"memory_kb\": 263042332,\n    \"memory_gb\": 250.9,\n    \"platform_id\": \"linux-threadripper-192c\",\n    \"compiler\": {\n      \"compiler_path\": \"/usr/bin/c++\",\n      \"build_type\": \"Release\",\n      \"cxx_standard\": \"20\",\n      \"compiler_id\": \"GNU\",\n      \"compiler_version\": \"15.2.1\",\n      \"compiler_summary\": \"GNU 15.2.1 Release C++20\"\n    }\n  },\n  \"results\": [\n    {\n      \"name\": \"cascading_parallel_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T07:38:20-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/cascading_parallel_for_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            14.5049,\n            28.4985,\n            22.1855\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1466619,\n            \"real_time\": 1433.2252991299833,\n            \"cpu_time\": 1419.2281580969566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/100000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13874,\n            \"real_time\": 150639.50850288518,\n            \"cpu_time\": 149098.23879198497,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/10000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77,\n            \"real_time\": 27316695.9742447,\n            \"cpu_time\": 27002613.974025987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 284976,\n            \"real_time\": 7433.991339623322,\n            \"cpu_time\": 7365.246754112632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113919,\n            \"real_time\": 16078.47437231796,\n            \"cpu_time\": 15956.523670327162,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 96870,\n            \"real_time\": 23430.244214023274,\n            \"cpu_time\": 23274.21957262311,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83169,\n            \"real_time\": 24824.41254587218,\n            \"cpu_time\": 24731.107696377254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83286,\n            \"real_time\": 19421.428259172004,\n            \"cpu_time\": 19303.643169320185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84426,\n            \"real_time\": 24581.34914679514,\n            \"cpu_time\": 24459.77029588038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66582,\n            \"real_time\": 28608.203102913663,\n            \"cpu_time\": 28394.318058934827,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65480,\n            \"real_time\": 32783.370219977776,\n            \"cpu_time\": 32574.191890653667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42478,\n            \"real_time\": 46944.24080683258,\n            \"cpu_time\": 46569.23885305334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34100,\n            \"real_time\": 59198.092111410944,\n            \"cpu_time\": 58727.7187683285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25890,\n            \"real_time\": 81956.91969797487,\n            \"cpu_time\": 81232.99181151015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19747,\n            \"real_time\": 106424.7751547934,\n            \"cpu_time\": 105388.6476426797,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13521,\n            \"real_time\": 155061.25812069332,\n            \"cpu_time\": 153479.03786702125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9854,\n            \"real_time\": 213324.40847163877,\n            \"cpu_time\": 211082.49391110247,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 236,\n            \"real_time\": 33721610.09327225,\n            \"cpu_time\": 32670107.550847456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_omp/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13130,\n            \"real_time\": 159872.02155234266,\n            \"cpu_time\": 158382.93191165273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_omp/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21076,\n            \"real_time\": 98067.4684004659,\n            \"cpu_time\": 97182.19814006455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_omp/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26182,\n            \"real_time\": 80454.20059407095,\n            \"cpu_time\": 79618.04132610199,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_omp/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32596,\n            \"real_time\": 67144.6689469462,\n            \"cpu_time\": 66604.48383237215,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_omp/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39087,\n            \"real_time\": 55964.44222031628,\n            \"cpu_time\": 55620.20809987961,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_omp/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41691,\n            \"real_time\": 47969.931303731566,\n            \"cpu_time\": 47566.39584082899,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_omp/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45387,\n            \"real_time\": 44616.355894388995,\n            \"cpu_time\": 44198.30647542253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_omp/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40083,\n            \"real_time\": 49247.61445053098,\n            \"cpu_time\": 48769.03724771088,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_omp/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35391,\n            \"real_time\": 61094.715520726924,\n            \"cpu_time\": 60761.03308750823,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_omp/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29240,\n            \"real_time\": 72138.56118349626,\n            \"cpu_time\": 71489.4794117644,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_omp/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22642,\n            \"real_time\": 93263.0810432683,\n            \"cpu_time\": 92183.25240703106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_omp/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17914,\n            \"real_time\": 116915.38601236366,\n            \"cpu_time\": 115608.42218376737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_omp/96/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11475,\n            \"real_time\": 171853.34684347536,\n            \"cpu_time\": 169547.8834858378,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_omp/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9468,\n            \"real_time\": 222402.01414646962,\n            \"cpu_time\": 219730.2516899038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_omp/192/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 56014082.13107405,\n            \"cpu_time\": 55594554.68421061,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_omp/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 28141241.971752606,\n            \"cpu_time\": 27893230.708333246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_omp/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 23961592.211363543,\n            \"cpu_time\": 23709887.684210505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_omp/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 19775310.862062518,\n            \"cpu_time\": 19552416.742574185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_omp/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 20505360.14023237,\n            \"cpu_time\": 20296823.24999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_omp/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 19671868.66910197,\n            \"cpu_time\": 19207019.69000007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_omp/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 215,\n            \"real_time\": 9831742.032127844,\n            \"cpu_time\": 9764588.804651123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_omp/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 278,\n            \"real_time\": 12212767.611632941,\n            \"cpu_time\": 12130962.338129459,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_omp/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 10737530.344737355,\n            \"cpu_time\": 10644280.939393947,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_omp/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 340,\n            \"real_time\": 6821168.2674968075,\n            \"cpu_time\": 6775358.547058835,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_omp/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418,\n            \"real_time\": 5388358.449697067,\n            \"cpu_time\": 5333214.56459329,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_omp/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 616,\n            \"real_time\": 3336718.295362185,\n            \"cpu_time\": 3311058.4675324783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_omp/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 758,\n            \"real_time\": 2724961.519743854,\n            \"cpu_time\": 2679440.105540902,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_omp/96/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 902,\n            \"real_time\": 2214681.2216285826,\n            \"cpu_time\": 2166333.9589800253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_omp/128/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 876,\n            \"real_time\": 2213046.312721268,\n            \"cpu_time\": 2178391.8721461277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_omp/192/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 56947737.388933696,\n            \"cpu_time\": 55794519.08333352,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10260,\n            \"real_time\": 198933.64094199566,\n            \"cpu_time\": 197414.27027290664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11707,\n            \"real_time\": 181178.50977872394,\n            \"cpu_time\": 179874.8154950032,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11388,\n            \"real_time\": 155757.8387740387,\n            \"cpu_time\": 154116.43774148106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13114,\n            \"real_time\": 152056.84276448246,\n            \"cpu_time\": 150702.03095928082,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14535,\n            \"real_time\": 121280.88654681788,\n            \"cpu_time\": 120108.09797041773,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15842,\n            \"real_time\": 127904.46490569755,\n            \"cpu_time\": 126808.77572276315,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16530,\n            \"real_time\": 125607.84682226961,\n            \"cpu_time\": 125182.4002419856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17822,\n            \"real_time\": 115169.55459628168,\n            \"cpu_time\": 114744.86617663596,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19361,\n            \"real_time\": 109557.46671139008,\n            \"cpu_time\": 108865.16641702421,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17557,\n            \"real_time\": 118259.59770990373,\n            \"cpu_time\": 117676.99567124121,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19087,\n            \"real_time\": 110183.69376962693,\n            \"cpu_time\": 109370.2007125269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18928,\n            \"real_time\": 111173.58717502355,\n            \"cpu_time\": 110253.40352916406,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18585,\n            \"real_time\": 112956.20182903424,\n            \"cpu_time\": 111472.34694646257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17555,\n            \"real_time\": 117958.73329843409,\n            \"cpu_time\": 116513.03127314162,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16310,\n            \"real_time\": 128183.382154162,\n            \"cpu_time\": 127571.8464132423,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2049,\n            \"real_time\": 1026516.0654023791,\n            \"cpu_time\": 1015771.6168862795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1971,\n            \"real_time\": 957365.4870926494,\n            \"cpu_time\": 947937.6920344939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2159,\n            \"real_time\": 1102143.7508089882,\n            \"cpu_time\": 1092760.4701250617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2474,\n            \"real_time\": 988306.6601000979,\n            \"cpu_time\": 980825.1434923206,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1961,\n            \"real_time\": 893393.1580934178,\n            \"cpu_time\": 887450.6879143188,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2278,\n            \"real_time\": 915672.8841105184,\n            \"cpu_time\": 907949.334064971,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2684,\n            \"real_time\": 776217.5186342198,\n            \"cpu_time\": 769647.8975409903,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2970,\n            \"real_time\": 705531.3538866563,\n            \"cpu_time\": 701772.6205387255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3614,\n            \"real_time\": 573279.3550034877,\n            \"cpu_time\": 569039.7147205342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4223,\n            \"real_time\": 489268.2841565021,\n            \"cpu_time\": 485844.12479280616,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5297,\n            \"real_time\": 394535.05191070074,\n            \"cpu_time\": 391833.266943555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6215,\n            \"real_time\": 336112.338380494,\n            \"cpu_time\": 333103.03266291413,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6552,\n            \"real_time\": 293141.49450994027,\n            \"cpu_time\": 289317.04609279695,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7002,\n            \"real_time\": 279125.51657129393,\n            \"cpu_time\": 275486.1458154803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7113,\n            \"real_time\": 296684.4456628568,\n            \"cpu_time\": 293742.3163222256,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 33081485.634633843,\n            \"cpu_time\": 32720783.500000022,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103,\n            \"real_time\": 23783631.68043383,\n            \"cpu_time\": 23580736.44660187,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 21404492.000779398,\n            \"cpu_time\": 21233644.551401865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123,\n            \"real_time\": 17684118.26853436,\n            \"cpu_time\": 17538481.80487809,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127,\n            \"real_time\": 16629882.771925136,\n            \"cpu_time\": 16506845.2992126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15109424.199908972,\n            \"cpu_time\": 14970329.189999916,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 159,\n            \"real_time\": 12930820.862258896,\n            \"cpu_time\": 12819958.194968535,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 11461749.349931074,\n            \"cpu_time\": 11370738.44623649,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 206,\n            \"real_time\": 10711736.66515252,\n            \"cpu_time\": 10635137.199029211,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 169,\n            \"real_time\": 10623305.763211653,\n            \"cpu_time\": 10569320.781064931,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 164,\n            \"real_time\": 11888728.280432478,\n            \"cpu_time\": 11803730.353658633,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 13802826.54701761,\n            \"cpu_time\": 13698028.397515647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 147,\n            \"real_time\": 13644273.156857714,\n            \"cpu_time\": 13412326.238095192,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15178413.239773365,\n            \"cpu_time\": 14961242.589999983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 132,\n            \"real_time\": 17276990.24239414,\n            \"cpu_time\": 16945398.159090918,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9598,\n            \"real_time\": 213915.5627250637,\n            \"cpu_time\": 211805.8225671965,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10817,\n            \"real_time\": 192088.05638498813,\n            \"cpu_time\": 190459.98197282403,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11509,\n            \"real_time\": 175063.17725305242,\n            \"cpu_time\": 173567.62412025302,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13198,\n            \"real_time\": 156806.49143186837,\n            \"cpu_time\": 155303.1206243368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14587,\n            \"real_time\": 137540.0302279798,\n            \"cpu_time\": 136231.2577637657,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16893,\n            \"real_time\": 122403.1308253494,\n            \"cpu_time\": 121113.21843367069,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19351,\n            \"real_time\": 104886.61170257218,\n            \"cpu_time\": 104290.94739289864,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_task_group/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22493,\n            \"real_time\": 93160.11399237876,\n            \"cpu_time\": 92252.13995465296,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_task_group/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27134,\n            \"real_time\": 76754.90141547972,\n            \"cpu_time\": 76017.28525097633,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_task_group/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31026,\n            \"real_time\": 66536.04051422417,\n            \"cpu_time\": 66221.4582608138,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_task_group/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36844,\n            \"real_time\": 56761.01577104626,\n            \"cpu_time\": 56256.777385733745,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_task_group/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40657,\n            \"real_time\": 51041.092578332966,\n            \"cpu_time\": 50493.183658410446,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_task_group/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43897,\n            \"real_time\": 46629.690433035066,\n            \"cpu_time\": 45982.47606897933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_task_group/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44082,\n            \"real_time\": 46020.03693160622,\n            \"cpu_time\": 45425.417335873455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_task_group/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39807,\n            \"real_time\": 47066.06885716968,\n            \"cpu_time\": 46861.00856633158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1963,\n            \"real_time\": 1071773.291415081,\n            \"cpu_time\": 1062331.1472236377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2600,\n            \"real_time\": 781596.7480508754,\n            \"cpu_time\": 775605.4738461688,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2680,\n            \"real_time\": 632527.2947928604,\n            \"cpu_time\": 626417.9179104625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3669,\n            \"real_time\": 522530.69828471803,\n            \"cpu_time\": 517402.263014445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2878,\n            \"real_time\": 583324.8871063414,\n            \"cpu_time\": 578506.6619179937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3445,\n            \"real_time\": 588184.2676244666,\n            \"cpu_time\": 585159.49927432,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4832,\n            \"real_time\": 450804.47435245645,\n            \"cpu_time\": 448212.7895281387,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb_task_group/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5250,\n            \"real_time\": 380071.9295229231,\n            \"cpu_time\": 376120.9809523778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb_task_group/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6455,\n            \"real_time\": 313979.94934118807,\n            \"cpu_time\": 311129.11432997766,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb_task_group/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7827,\n            \"real_time\": 264042.1072059679,\n            \"cpu_time\": 262440.32809505454,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb_task_group/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10351,\n            \"real_time\": 203398.59173080805,\n            \"cpu_time\": 202012.96444788092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb_task_group/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11680,\n            \"real_time\": 174370.6011202199,\n            \"cpu_time\": 172452.03219177903,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/96/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb_task_group/96/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13434,\n            \"real_time\": 150160.3081067576,\n            \"cpu_time\": 148030.938439778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/128/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb_task_group/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15714,\n            \"real_time\": 143185.85713128824,\n            \"cpu_time\": 141353.70154002972,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/192/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb_task_group/192/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9985,\n            \"real_time\": 165620.78308088367,\n            \"cpu_time\": 143700.76154231498,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 32811250.940743666,\n            \"cpu_time\": 32492507.08955233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86,\n            \"real_time\": 24840233.605192583,\n            \"cpu_time\": 24548114.220930647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 95,\n            \"real_time\": 23003428.25290404,\n            \"cpu_time\": 22814382.97894738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122,\n            \"real_time\": 20658376.589455627,\n            \"cpu_time\": 20498641.459016375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122,\n            \"real_time\": 16284406.253854271,\n            \"cpu_time\": 16132455.745901842,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 132,\n            \"real_time\": 16121470.65867303,\n            \"cpu_time\": 16010423.909091115,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 132,\n            \"real_time\": 13186186.484138792,\n            \"cpu_time\": 13037691.287879074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb_task_group/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 185,\n            \"real_time\": 11967703.426961562,\n            \"cpu_time\": 11847729.956756715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb_task_group/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 178,\n            \"real_time\": 12018358.325742686,\n            \"cpu_time\": 11920957.52247181,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb_task_group/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187,\n            \"real_time\": 10882708.165585436,\n            \"cpu_time\": 10784798.026738195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb_task_group/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 11134406.44139489,\n            \"cpu_time\": 11052982.534883691,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb_task_group/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 173,\n            \"real_time\": 12386022.635595605,\n            \"cpu_time\": 12299076.127167523,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/96/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb_task_group/96/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 166,\n            \"real_time\": 13169826.072197497,\n            \"cpu_time\": 13004327.355422009,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/128/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb_task_group/128/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 156,\n            \"real_time\": 14150836.063960854,\n            \"cpu_time\": 13968463.673076935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/192/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb_task_group/192/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 16822532.53995441,\n            \"cpu_time\": 16334112.17999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1275424,\n            \"real_time\": 1597.6526786908753,\n            \"cpu_time\": 1581.5310461462236,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1306322,\n            \"real_time\": 1595.858442974583,\n            \"cpu_time\": 1579.5120368485,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1279342,\n            \"real_time\": 1639.88987622159,\n            \"cpu_time\": 1624.4220005283935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1286750,\n            \"real_time\": 1606.382994328294,\n            \"cpu_time\": 1589.7305342918191,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1246534,\n            \"real_time\": 1617.622812578432,\n            \"cpu_time\": 1603.834055067872,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1295791,\n            \"real_time\": 1595.2067424726015,\n            \"cpu_time\": 1578.8362019801061,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1323083,\n            \"real_time\": 1610.6311025143316,\n            \"cpu_time\": 1593.1341268839226,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_blocking/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1323016,\n            \"real_time\": 1620.081878863651,\n            \"cpu_time\": 1602.7177622946433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_blocking/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1294772,\n            \"real_time\": 1599.3818494617303,\n            \"cpu_time\": 1583.9352048082535,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_blocking/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1329852,\n            \"real_time\": 1579.6567483116764,\n            \"cpu_time\": 1565.5085468157176,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_blocking/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1311262,\n            \"real_time\": 1583.2650767543917,\n            \"cpu_time\": 1570.7045159548418,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_blocking/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1296453,\n            \"real_time\": 1603.1236496781287,\n            \"cpu_time\": 1590.8238385810832,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/96/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_blocking/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1275776,\n            \"real_time\": 1606.8433902293584,\n            \"cpu_time\": 1597.3386291951222,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/128/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_blocking/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1281346,\n            \"real_time\": 1654.8264481226076,\n            \"cpu_time\": 1641.579137094893,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/192/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_blocking/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1270624,\n            \"real_time\": 1608.7302561440433,\n            \"cpu_time\": 1595.1131176492936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13502,\n            \"real_time\": 152420.8559519597,\n            \"cpu_time\": 150831.42178936146,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19153,\n            \"real_time\": 110566.14128587516,\n            \"cpu_time\": 109479.54748603354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16551,\n            \"real_time\": 139427.52661387512,\n            \"cpu_time\": 138189.63397982068,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19192,\n            \"real_time\": 114324.97441649658,\n            \"cpu_time\": 113350.68278449272,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18581,\n            \"real_time\": 122549.50223636653,\n            \"cpu_time\": 121566.3421774935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 248321.68449647722,\n            \"cpu_time\": 246850.54790000434,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10206,\n            \"real_time\": 212355.34019759845,\n            \"cpu_time\": 211079.3937879688,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_blocking/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12936,\n            \"real_time\": 166573.28223583536,\n            \"cpu_time\": 165796.0016233768,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_blocking/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14312,\n            \"real_time\": 147103.93585910206,\n            \"cpu_time\": 145626.58461430782,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_blocking/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17192,\n            \"real_time\": 133182.93788038037,\n            \"cpu_time\": 132154.3074685905,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_blocking/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14920,\n            \"real_time\": 131096.2630668655,\n            \"cpu_time\": 130439.99738605747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_blocking/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13098,\n            \"real_time\": 147299.6465052916,\n            \"cpu_time\": 145809.3618109632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/96/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_blocking/96/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10157,\n            \"real_time\": 194120.95353327875,\n            \"cpu_time\": 191832.04597813895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/128/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_blocking/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7041,\n            \"real_time\": 238309.15041857274,\n            \"cpu_time\": 229605.21687260416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/192/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_blocking/192/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4298,\n            \"real_time\": 559008.5814474692,\n            \"cpu_time\": 350562.7408096766,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 27044821.9201838,\n            \"cpu_time\": 26734496.159999706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 23818691.519554704,\n            \"cpu_time\": 23592028.34999962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 21320658.69002065,\n            \"cpu_time\": 21090581.83098546,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86,\n            \"real_time\": 22802100.98793167,\n            \"cpu_time\": 22608012.61627884,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 22022598.94501377,\n            \"cpu_time\": 21795531.7472529,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 119,\n            \"real_time\": 19669715.201623052,\n            \"cpu_time\": 19486316.42857103,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 132,\n            \"real_time\": 16044864.386926886,\n            \"cpu_time\": 15909318.71969691,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_blocking/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15773170.130560175,\n            \"cpu_time\": 15623738.789999492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_blocking/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154,\n            \"real_time\": 13811662.143047947,\n            \"cpu_time\": 13673520.772727357,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_blocking/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 168,\n            \"real_time\": 13959985.89855264,\n            \"cpu_time\": 13862351.738095094,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_blocking/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 150,\n            \"real_time\": 14979659.433010966,\n            \"cpu_time\": 14866908.526666597,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_blocking/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 143,\n            \"real_time\": 15190604.343111595,\n            \"cpu_time\": 15075996.349650383,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/96/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_blocking/96/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 142,\n            \"real_time\": 14973404.627083473,\n            \"cpu_time\": 14799341.352112954,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/128/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_blocking/128/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15242423.189338299,\n            \"cpu_time\": 13779709.220000312,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/192/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_blocking/192/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 16100644.620601086,\n            \"cpu_time\": 12090932.61000021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1341848,\n            \"real_time\": 1520.4995647436147,\n            \"cpu_time\": 1504.9425926036524,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000,\n            \"real_time\": 1587.6488299109042,\n            \"cpu_time\": 1571.714233000023,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1316052,\n            \"real_time\": 1562.2868869101796,\n            \"cpu_time\": 1546.0628447811396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1351049,\n            \"real_time\": 1563.2679377723327,\n            \"cpu_time\": 1547.374042688329,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1297175,\n            \"real_time\": 1571.8059568422946,\n            \"cpu_time\": 1554.6349821727752,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1335590,\n            \"real_time\": 1589.0819248360149,\n            \"cpu_time\": 1571.4807336083697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1317072,\n            \"real_time\": 1577.5689309645477,\n            \"cpu_time\": 1560.4497438256744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_cascaded/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1306692,\n            \"real_time\": 1561.6740854247107,\n            \"cpu_time\": 1544.5849488632048,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_cascaded/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1352591,\n            \"real_time\": 1572.0296312435535,\n            \"cpu_time\": 1559.7796532728796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_cascaded/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1373694,\n            \"real_time\": 1504.2616602293667,\n            \"cpu_time\": 1490.0046254842725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_cascaded/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1373875,\n            \"real_time\": 1563.806343441008,\n            \"cpu_time\": 1546.1980456738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_cascaded/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1329318,\n            \"real_time\": 1559.0777526470263,\n            \"cpu_time\": 1542.747335099585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/96/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_cascaded/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1254097,\n            \"real_time\": 1580.6408682791498,\n            \"cpu_time\": 1564.3962436717302,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/128/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_cascaded/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1272460,\n            \"real_time\": 1524.481064226941,\n            \"cpu_time\": 1509.2761163416094,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/192/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_cascaded/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1279013,\n            \"real_time\": 1588.7388651041745,\n            \"cpu_time\": 1572.289867264786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13452,\n            \"real_time\": 155806.0507019226,\n            \"cpu_time\": 154091.33363068505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9534,\n            \"real_time\": 344469.0263342876,\n            \"cpu_time\": 340899.08328089054,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22084,\n            \"real_time\": 80005.01594118224,\n            \"cpu_time\": 79133.45784277876,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28526,\n            \"real_time\": 79085.78889543329,\n            \"cpu_time\": 78261.01833415123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29894,\n            \"real_time\": 57769.40553521435,\n            \"cpu_time\": 57178.98942931936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12933,\n            \"real_time\": 126800.94548960723,\n            \"cpu_time\": 126018.0549756492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15501,\n            \"real_time\": 140472.3950024435,\n            \"cpu_time\": 139489.27869169443,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_cascaded/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16924,\n            \"real_time\": 122526.22979598024,\n            \"cpu_time\": 121838.07580950159,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_cascaded/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19985,\n            \"real_time\": 106495.47675679946,\n            \"cpu_time\": 105654.56592443858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_cascaded/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22817,\n            \"real_time\": 91151.52776202282,\n            \"cpu_time\": 90663.61725906483,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_cascaded/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24292,\n            \"real_time\": 88426.68602711258,\n            \"cpu_time\": 87914.96743783842,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_cascaded/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19559,\n            \"real_time\": 109635.16350378637,\n            \"cpu_time\": 109122.58090904298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/96/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_cascaded/96/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12431,\n            \"real_time\": 150894.23119802756,\n            \"cpu_time\": 149091.82535596343,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/128/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_cascaded/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9615,\n            \"real_time\": 204875.0882977993,\n            \"cpu_time\": 202700.13832553616,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/192/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_cascaded/192/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6177,\n            \"real_time\": 376090.02265629283,\n            \"cpu_time\": 307769.0497004935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 26952636.24036064,\n            \"cpu_time\": 26616094.786666814,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 40439965.76906349,\n            \"cpu_time\": 40002735.653845966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 82,\n            \"real_time\": 23737628.49985236,\n            \"cpu_time\": 23472050.073171042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 22643515.63838621,\n            \"cpu_time\": 22335152.457143135,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 19997795.55388717,\n            \"cpu_time\": 19689392.643564846,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 17447722.88016975,\n            \"cpu_time\": 17137007.820000462,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 157,\n            \"real_time\": 13471732.165955102,\n            \"cpu_time\": 13289283.00000055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_cascaded/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 179,\n            \"real_time\": 11587558.85465747,\n            \"cpu_time\": 11429402.93854733,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_cascaded/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 10471183.114568703,\n            \"cpu_time\": 10338719.270000068,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_cascaded/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187,\n            \"real_time\": 10778084.486339461,\n            \"cpu_time\": 10650977.518716924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_cascaded/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 12134331.22029528,\n            \"cpu_time\": 12026523.67741973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_cascaded/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 13636197.925370652,\n            \"cpu_time\": 13529918.056249812,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/96/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_cascaded/96/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 13122847.446917284,\n            \"cpu_time\": 12570699.037267031,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/128/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_cascaded/128/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 13663618.960294453,\n            \"cpu_time\": 11757497.622516708,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/192/10000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_cascaded/192/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15046445.830957964,\n            \"cpu_time\": 9755741.720000515,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"concurrent_vector_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T07:49:00-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/concurrent_vector_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            42.9346,\n            34.7827,\n            29.6118\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_std_push_back_serial\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 752,\n            \"real_time\": 2766462.8017946407,\n            \"cpu_time\": 2738773.704787234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_push_back_serial\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3848,\n            \"real_time\": 551471.3684873842,\n            \"cpu_time\": 545859.0849792098,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 488,\n            \"real_time\": 4442104.092392627,\n            \"cpu_time\": 4396601.540983606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 372,\n            \"real_time\": 5819354.911074444,\n            \"cpu_time\": 5757064.760752691,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 927,\n            \"real_time\": 2332591.390545644,\n            \"cpu_time\": 2310314.833872708,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9958,\n            \"real_time\": 223395.30517935433,\n            \"cpu_time\": 221118.36081542468,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_push_back_serial_reserve\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9692,\n            \"real_time\": 223203.1628181616,\n            \"cpu_time\": 220884.06954189035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_reserve\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 469,\n            \"real_time\": 4571737.30703448,\n            \"cpu_time\": 4530893.002132201,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1118,\n            \"real_time\": 1895297.0268256455,\n            \"cpu_time\": 1874853.8184257606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 781,\n            \"real_time\": 2695541.726019849,\n            \"cpu_time\": 2670335.591549293,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9682,\n            \"real_time\": 223321.78496535768,\n            \"cpu_time\": 220949.86944846105,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18981,\n            \"real_time\": 110669.9320345043,\n            \"cpu_time\": 109551.47168220834,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5442,\n            \"real_time\": 410258.408121762,\n            \"cpu_time\": 406227.5922454979,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3260,\n            \"real_time\": 641485.3257807029,\n            \"cpu_time\": 635331.0981595082,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6093,\n            \"real_time\": 332545.37928740017,\n            \"cpu_time\": 329104.69210569514,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate_reverse\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19490,\n            \"real_time\": 107676.25464416042,\n            \"cpu_time\": 106612.48424833242,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate_reverse\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5302,\n            \"real_time\": 397184.4517098201,\n            \"cpu_time\": 393120.9866088272,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate_reverse\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4498,\n            \"real_time\": 477181.0640233518,\n            \"cpu_time\": 472225.40017785795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate_reverse\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4906,\n            \"real_time\": 440458.46819967986,\n            \"cpu_time\": 436056.57562168746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_lower_bound\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 26521525.519628882,\n            \"cpu_time\": 26262771.911392346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_lower_bound\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60,\n            \"real_time\": 35525346.1166285,\n            \"cpu_time\": 35155088.49999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_lower_bound\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 34023883.50150432,\n            \"cpu_time\": 33798048.96874994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_lower_bound\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 37957291.983886905,\n            \"cpu_time\": 37533913.20689659,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_index\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19271,\n            \"real_time\": 108173.62181808498,\n            \"cpu_time\": 107061.36692439407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_index\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3313,\n            \"real_time\": 642129.8376002585,\n            \"cpu_time\": 635713.2782976173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_index\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3880,\n            \"real_time\": 535368.4716536328,\n            \"cpu_time\": 529771.4865979363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_index\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3562,\n            \"real_time\": 576431.0519265378,\n            \"cpu_time\": 570487.4856821998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_random\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2657,\n            \"real_time\": 803848.9932213981,\n            \"cpu_time\": 794526.4546480963,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_random\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1248,\n            \"real_time\": 1579802.078478492,\n            \"cpu_time\": 1564108.4703525587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_random\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1790,\n            \"real_time\": 1248877.8229209713,\n            \"cpu_time\": 1237242.664804466,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_random\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1464,\n            \"real_time\": 1447134.739747958,\n            \"cpu_time\": 1432344.7752732264,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 130854719.29105765,\n            \"cpu_time\": 122809665.00000043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 137590424.1165913,\n            \"cpu_time\": 129346015.17647044,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel\",\n            \"family_index\": 33,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115,\n            \"real_time\": 35857174.60828955,\n            \"cpu_time\": 26034102.85217389,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel\",\n            \"family_index\": 34,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 42354153.33487953,\n            \"cpu_time\": 41472078.6410258,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_reserve\",\n            \"family_index\": 35,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 127547476.60882357,\n            \"cpu_time\": 116926024.49999927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_reserve\",\n            \"family_index\": 36,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 36634093.21223188,\n            \"cpu_time\": 26135766.863636263,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_reserve\",\n            \"family_index\": 37,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 20481351.95260069,\n            \"cpu_time\": 19788357.209523745,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_clear\",\n            \"family_index\": 38,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 121309710.7764851,\n            \"cpu_time\": 115328852.05555488,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_clear\",\n            \"family_index\": 39,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 139075949.38063994,\n            \"cpu_time\": 130123559.43750009,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_clear\",\n            \"family_index\": 40,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 36209473.991148435,\n            \"cpu_time\": 26418202.27433625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_clear\",\n            \"family_index\": 41,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106,\n            \"real_time\": 20661971.972209737,\n            \"cpu_time\": 20092523.89622646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_10\",\n            \"family_index\": 42,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 63,\n            \"real_time\": 33937473.810972676,\n            \"cpu_time\": 32639038.63492082,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_10\",\n            \"family_index\": 43,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 48044665.42678866,\n            \"cpu_time\": 44862074.63829799,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_10\",\n            \"family_index\": 44,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 431,\n            \"real_time\": 5986262.531518902,\n            \"cpu_time\": 5837509.074245925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"family_index\": 45,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 850,\n            \"real_time\": 2491046.171772348,\n            \"cpu_time\": 2419358.322352941,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_100\",\n            \"family_index\": 46,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 14662358.529760892,\n            \"cpu_time\": 13263495.94701987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_100\",\n            \"family_index\": 47,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 237,\n            \"real_time\": 18396568.97040501,\n            \"cpu_time\": 8162850.118143484,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_100\",\n            \"family_index\": 48,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1851996.9759508967,\n            \"cpu_time\": 1626162.8550000181,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"family_index\": 49,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7529,\n            \"real_time\": 303953.9488707109,\n            \"cpu_time\": 296349.11223269865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_max\",\n            \"family_index\": 50,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2971,\n            \"real_time\": 6523151.980814574,\n            \"cpu_time\": 1635274.04140021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_max\",\n            \"family_index\": 51,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 890,\n            \"real_time\": 5782772.299933007,\n            \"cpu_time\": 2154925.058426974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_max\",\n            \"family_index\": 52,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3334,\n            \"real_time\": 638700.5620856725,\n            \"cpu_time\": 632812.0062987359,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"family_index\": 53,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34159,\n            \"real_time\": 70178.59761575396,\n            \"cpu_time\": 61097.10626774745,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_each_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T07:52:05-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/for_each_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            83.9683,\n            53.207,\n            37.0181\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14633484,\n            \"real_time\": 143.16154594771086,\n            \"cpu_time\": 141.7786765612345,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14604,\n            \"real_time\": 148511.11531115035,\n            \"cpu_time\": 147058.36483155296,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 22022279.255597435,\n            \"cpu_time\": 21744333.46808511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4150106,\n            \"real_time\": 504.1451565406422,\n            \"cpu_time\": 499.2063397898751,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2718009,\n            \"real_time\": 776.1207873219112,\n            \"cpu_time\": 767.7490788293926,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2690653,\n            \"real_time\": 813.9299861373033,\n            \"cpu_time\": 805.2857284086801,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2322202,\n            \"real_time\": 906.9246215452739,\n            \"cpu_time\": 898.5589470683433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1838330,\n            \"real_time\": 1213.149196869415,\n            \"cpu_time\": 1202.963119244097,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1140648,\n            \"real_time\": 1491.4937167165792,\n            \"cpu_time\": 1473.3164438108874,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 578168,\n            \"real_time\": 3198.479040811303,\n            \"cpu_time\": 3173.6384493780397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 490702,\n            \"real_time\": 3944.953562403192,\n            \"cpu_time\": 3905.8883660551614,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388025,\n            \"real_time\": 5288.227189100151,\n            \"cpu_time\": 5253.74947748213,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 294403,\n            \"real_time\": 7021.325825289052,\n            \"cpu_time\": 6974.402268319259,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 204120,\n            \"real_time\": 9814.161644778034,\n            \"cpu_time\": 9730.779928473446,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160632,\n            \"real_time\": 12589.963699656302,\n            \"cpu_time\": 12507.705892972772,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113231,\n            \"real_time\": 19302.748364242198,\n            \"cpu_time\": 19139.737395236338,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77968,\n            \"real_time\": 27146.68666760577,\n            \"cpu_time\": 25857.47873486565,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47004,\n            \"real_time\": 52255.37526613838,\n            \"cpu_time\": 36646.701216917754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4292,\n            \"real_time\": 499676.7336804722,\n            \"cpu_time\": 494462.51677539706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8226,\n            \"real_time\": 254567.7460576101,\n            \"cpu_time\": 251663.27972283048,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12083,\n            \"real_time\": 171683.6246793721,\n            \"cpu_time\": 169897.27534552652,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15830,\n            \"real_time\": 134198.74024236796,\n            \"cpu_time\": 133031.57473152256,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23256,\n            \"real_time\": 91573.577828548,\n            \"cpu_time\": 90729.45841933273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27952,\n            \"real_time\": 73578.0301553282,\n            \"cpu_time\": 72936.00232541459,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36298,\n            \"real_time\": 51622.27599603409,\n            \"cpu_time\": 51111.604165518795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47078,\n            \"real_time\": 48382.789924323144,\n            \"cpu_time\": 48132.80254046477,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50555,\n            \"real_time\": 47700.51891840983,\n            \"cpu_time\": 47200.957452279894,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44694,\n            \"real_time\": 42158.06311678808,\n            \"cpu_time\": 41756.40891394826,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54353,\n            \"real_time\": 40873.119955248076,\n            \"cpu_time\": 40661.89879123503,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50235,\n            \"real_time\": 37939.86049661772,\n            \"cpu_time\": 37557.044391360665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/96/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49634,\n            \"real_time\": 40546.231674874114,\n            \"cpu_time\": 39926.866301325674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/128/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46111,\n            \"real_time\": 44040.33404056522,\n            \"cpu_time\": 42487.208778816224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/192/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30901,\n            \"real_time\": 74040.2906710615,\n            \"cpu_time\": 48436.8772855246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 51538677.27968582,\n            \"cpu_time\": 51036377.302325346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 25965838.741948023,\n            \"cpu_time\": 25669375.086419642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 116,\n            \"real_time\": 18707137.439472213,\n            \"cpu_time\": 18490827.344827577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 16631091.10901132,\n            \"cpu_time\": 16434846.000000078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 178,\n            \"real_time\": 11993987.88210172,\n            \"cpu_time\": 11880173.662921315,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 11844514.466722868,\n            \"cpu_time\": 11700980.177664993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 220,\n            \"real_time\": 9716727.94125466,\n            \"cpu_time\": 9610487.699999997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_for_each_n/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 351,\n            \"real_time\": 7416418.489888629,\n            \"cpu_time\": 7334982.139601147,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_for_each_n/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 390,\n            \"real_time\": 6219252.204904571,\n            \"cpu_time\": 6156283.905128189,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_for_each_n/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 386,\n            \"real_time\": 5572207.650251764,\n            \"cpu_time\": 5530243.507772012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_for_each_n/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 394,\n            \"real_time\": 5483320.050844497,\n            \"cpu_time\": 5402103.69035531,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_for_each_n/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 379,\n            \"real_time\": 5541364.97074232,\n            \"cpu_time\": 5489273.451187372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/96/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_for_each_n/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 377,\n            \"real_time\": 5747581.026467447,\n            \"cpu_time\": 5661748.543766591,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/128/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_for_each_n/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 369,\n            \"real_time\": 5954843.682683702,\n            \"cpu_time\": 4833669.745257492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/192/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_for_each_n/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 343,\n            \"real_time\": 6479821.017191206,\n            \"cpu_time\": 3619500.306122451,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1525632,\n            \"real_time\": 1386.855807290837,\n            \"cpu_time\": 1373.2469252087055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 598363,\n            \"real_time\": 3641.7574130289217,\n            \"cpu_time\": 3601.563161492317,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 539891,\n            \"real_time\": 4108.569416704429,\n            \"cpu_time\": 4066.523590873006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 457335,\n            \"real_time\": 4606.53279316108,\n            \"cpu_time\": 4563.774891490975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 399170,\n            \"real_time\": 5205.444437046043,\n            \"cpu_time\": 5173.534013077171,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 340742,\n            \"real_time\": 6122.559341145662,\n            \"cpu_time\": 6089.07094810736,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 257899,\n            \"real_time\": 7741.884137158194,\n            \"cpu_time\": 7664.156092113489,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_deque/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 225476,\n            \"real_time\": 9316.01166410268,\n            \"cpu_time\": 9234.294328443013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_deque/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186669,\n            \"real_time\": 11401.281321257931,\n            \"cpu_time\": 11290.48584928412,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_deque/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 153145,\n            \"real_time\": 13557.487687704679,\n            \"cpu_time\": 13451.139906624423,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_deque/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 121379,\n            \"real_time\": 16982.930465857924,\n            \"cpu_time\": 16865.446856540377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_deque/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102090,\n            \"real_time\": 21488.37703942905,\n            \"cpu_time\": 21333.10217455185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/96/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_deque/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78130,\n            \"real_time\": 27163.692871145602,\n            \"cpu_time\": 26762.68118520399,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/128/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_deque/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61799,\n            \"real_time\": 34351.81184225907,\n            \"cpu_time\": 33718.80098383479,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/192/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_deque/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29871,\n            \"real_time\": 60665.23698735639,\n            \"cpu_time\": 47903.2303572028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1266,\n            \"real_time\": 1585976.955021833,\n            \"cpu_time\": 1569219.825434445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 595,\n            \"real_time\": 3476038.7747415476,\n            \"cpu_time\": 3443716.744537814,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 573,\n            \"real_time\": 3726545.8236892186,\n            \"cpu_time\": 3690165.1710297023,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 526,\n            \"real_time\": 3797711.5057245917,\n            \"cpu_time\": 3764270.549429611,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 529,\n            \"real_time\": 4120211.8203029847,\n            \"cpu_time\": 4089836.2287334115,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 534,\n            \"real_time\": 4276171.606775261,\n            \"cpu_time\": 4239531.584269674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 422,\n            \"real_time\": 4621482.46913707,\n            \"cpu_time\": 4583149.850710888,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_deque/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 474,\n            \"real_time\": 4750895.320795446,\n            \"cpu_time\": 4707631.156118158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_deque/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 408,\n            \"real_time\": 5262994.740156037,\n            \"cpu_time\": 5223501.29656859,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n_deque/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 397,\n            \"real_time\": 5344901.337424383,\n            \"cpu_time\": 5303214.3526448915,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n_deque/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 380,\n            \"real_time\": 5361636.694655509,\n            \"cpu_time\": 5315152.139473717,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n_deque/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 5548144.477419555,\n            \"cpu_time\": 5507827.781333314,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/96/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n_deque/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 363,\n            \"real_time\": 5985087.490276262,\n            \"cpu_time\": 5903431.355371929,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/128/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n_deque/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 253,\n            \"real_time\": 8301171.513730771,\n            \"cpu_time\": 7456517.11857712,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/192/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n_deque/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 192,\n            \"real_time\": 10954535.130319225,\n            \"cpu_time\": 7111589.921874995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 158208208.45412806,\n            \"cpu_time\": 156563747.69230735,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 368762707.1381679,\n            \"cpu_time\": 365390110.2857162,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 376320401.49765086,\n            \"cpu_time\": 372554190.83333176,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 378984489.8041338,\n            \"cpu_time\": 375167200.7999957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 375148260.0113377,\n            \"cpu_time\": 371427194.59999967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 379307672.8004962,\n            \"cpu_time\": 375960156.3999979,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 458390798.39643085,\n            \"cpu_time\": 454428526.6000031,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_for_each_n_deque/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 481957544.782199,\n            \"cpu_time\": 477608078.000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_for_each_n_deque/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 509265998.727642,\n            \"cpu_time\": 504993326.75000376,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_for_each_n_deque/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 503674935.22935545,\n            \"cpu_time\": 499944502.0000053,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_for_each_n_deque/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 523600320.5063753,\n            \"cpu_time\": 518301560.7500039,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_for_each_n_deque/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 531398056.24959993,\n            \"cpu_time\": 525224804.7500103,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/96/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_for_each_n_deque/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 588600624.7601472,\n            \"cpu_time\": 566950684.9999948,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/128/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_for_each_n_deque/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 621148942.3488578,\n            \"cpu_time\": 611464453.9999858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/192/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_for_each_n_deque/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 886804518.988356,\n            \"cpu_time\": 811486442.9999973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 641497,\n            \"real_time\": 3171.3590820214054,\n            \"cpu_time\": 3140.9085451685546,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 361667,\n            \"real_time\": 6103.33547714431,\n            \"cpu_time\": 6043.379827299647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 309950,\n            \"real_time\": 6815.720500013154,\n            \"cpu_time\": 6748.583319890417,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 274546,\n            \"real_time\": 7595.940763970903,\n            \"cpu_time\": 7541.59172233425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 248432,\n            \"real_time\": 8344.007434630143,\n            \"cpu_time\": 8270.912652154224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 232739,\n            \"real_time\": 9400.140711449747,\n            \"cpu_time\": 9329.349417158262,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 184060,\n            \"real_time\": 11093.938753262242,\n            \"cpu_time\": 10980.549255677515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_list/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180737,\n            \"real_time\": 11691.362344246225,\n            \"cpu_time\": 11629.24178225799,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_list/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 155034,\n            \"real_time\": 13274.637421139334,\n            \"cpu_time\": 13176.18686223684,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_list/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 144001,\n            \"real_time\": 14953.140193234138,\n            \"cpu_time\": 14822.33075464724,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_list/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124226,\n            \"real_time\": 16952.032916209282,\n            \"cpu_time\": 16839.140485888947,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_list/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108821,\n            \"real_time\": 19074.137483038514,\n            \"cpu_time\": 18894.386781963087,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/96/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_list/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93158,\n            \"real_time\": 22254.52252049462,\n            \"cpu_time\": 22061.849417119738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/128/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_list/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74155,\n            \"real_time\": 26730.257272017025,\n            \"cpu_time\": 26243.09903580358,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/192/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_list/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35729,\n            \"real_time\": 61655.226285947356,\n            \"cpu_time\": 39600.66993198746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 705,\n            \"real_time\": 3263128.5914636035,\n            \"cpu_time\": 3237368.052482323,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 246,\n            \"real_time\": 10622687.987525137,\n            \"cpu_time\": 10516183.223577252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 251,\n            \"real_time\": 10085783.621474387,\n            \"cpu_time\": 9985228.61354592,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 247,\n            \"real_time\": 10070881.947709119,\n            \"cpu_time\": 9976519.55060726,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 261,\n            \"real_time\": 10675387.1456802,\n            \"cpu_time\": 10576563.371647716,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 12962231.507671403,\n            \"cpu_time\": 12850260.802030321,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 190,\n            \"real_time\": 11936113.489546666,\n            \"cpu_time\": 11833829.005263098,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_list/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 190,\n            \"real_time\": 12070036.420941744,\n            \"cpu_time\": 11972011.557894815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_list/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 166,\n            \"real_time\": 14066570.138289446,\n            \"cpu_time\": 13958004.680722661,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n_list/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154,\n            \"real_time\": 14206274.214515148,\n            \"cpu_time\": 14070365.616883142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n_list/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 14649974.77465189,\n            \"cpu_time\": 14525305.661290271,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n_list/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 139,\n            \"real_time\": 13690328.503550172,\n            \"cpu_time\": 13561888.438848753,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/96/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n_list/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 138,\n            \"real_time\": 14761054.18059624,\n            \"cpu_time\": 14618778.623188753,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/128/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n_list/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 121,\n            \"real_time\": 16547708.57104185,\n            \"cpu_time\": 15939049.46280991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/192/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n_list/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92,\n            \"real_time\": 17139018.46770845,\n            \"cpu_time\": 13281723.282608975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1741549,\n            \"real_time\": 1196.9445597559518,\n            \"cpu_time\": 1185.457927396819,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 790709,\n            \"real_time\": 2198.8438946339147,\n            \"cpu_time\": 2180.6060763188284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 618324,\n            \"real_time\": 2527.68118657745,\n            \"cpu_time\": 2507.5024032707665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 602962,\n            \"real_time\": 2664.1779714657087,\n            \"cpu_time\": 2639.348854488274,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 615701,\n            \"real_time\": 2930.5785356735632,\n            \"cpu_time\": 2904.242023319781,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 598480,\n            \"real_time\": 3497.870373176733,\n            \"cpu_time\": 3471.3788497527166,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 450069,\n            \"real_time\": 4710.616894304418,\n            \"cpu_time\": 4685.705829550608,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/16/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_set/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 395524,\n            \"real_time\": 5396.115012094816,\n            \"cpu_time\": 5360.162174735291,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/24/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_set/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 320585,\n            \"real_time\": 6471.084411088349,\n            \"cpu_time\": 6418.200680006807,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/32/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_set/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 282581,\n            \"real_time\": 7653.727108285104,\n            \"cpu_time\": 7604.9034648472325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/48/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_set/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 196478,\n            \"real_time\": 10449.629419136583,\n            \"cpu_time\": 10409.037943179317,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/64/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_set/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154325,\n            \"real_time\": 13398.762604364425,\n            \"cpu_time\": 13299.642812246693,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/96/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_set/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105163,\n            \"real_time\": 19365.62028482073,\n            \"cpu_time\": 19130.296092732187,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/128/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_set/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79542,\n            \"real_time\": 24608.7401998643,\n            \"cpu_time\": 24282.757637474147,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/192/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_set/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39843,\n            \"real_time\": 54713.62043483473,\n            \"cpu_time\": 37113.21436638833,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1673777,\n            \"real_time\": 1260.2231408018342,\n            \"cpu_time\": 1248.726079997518,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 820463,\n            \"real_time\": 2095.8539969954236,\n            \"cpu_time\": 2072.487207832698,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 735341,\n            \"real_time\": 2348.9970027813993,\n            \"cpu_time\": 2330.6041632385754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 622773,\n            \"real_time\": 2576.933211569972,\n            \"cpu_time\": 2552.1714364624245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 512130,\n            \"real_time\": 3082.9263410781014,\n            \"cpu_time\": 3061.1226875989214,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 519794,\n            \"real_time\": 3889.0391462683524,\n            \"cpu_time\": 3862.1948271815395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 397821,\n            \"real_time\": 4926.839427716214,\n            \"cpu_time\": 4901.193008916078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_set/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 376965,\n            \"real_time\": 5405.769002244411,\n            \"cpu_time\": 5382.704301460389,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_set/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 322274,\n            \"real_time\": 6555.443706214966,\n            \"cpu_time\": 6511.799806996512,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n_set/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 272508,\n            \"real_time\": 7791.740018662105,\n            \"cpu_time\": 7750.4932699223755,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n_set/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 199952,\n            \"real_time\": 10605.03160251244,\n            \"cpu_time\": 10540.836860846739,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n_set/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154665,\n            \"real_time\": 13642.709132193484,\n            \"cpu_time\": 13538.079733617757,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/96/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n_set/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98082,\n            \"real_time\": 21116.743286699104,\n            \"cpu_time\": 20924.403295202235,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/128/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n_set/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77648,\n            \"real_time\": 28050.257882473034,\n            \"cpu_time\": 27435.065552235843,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/192/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n_set/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32329,\n            \"real_time\": 54034.11351733718,\n            \"cpu_time\": 37919.858424326274,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_latency_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T07:59:37-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/for_latency_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            43.3701,\n            40.4067,\n            36.3809\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60,\n            \"real_time\": 35209832.91673474,\n            \"cpu_time\": 5078476.316666667,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005133739833642418,\n            \"stddev\": 0.00048537739306183763\n          },\n          {\n            \"name\": \"BM_omp/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 35829096.43039878,\n            \"cpu_time\": 5687969.327586207,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005755029733148243,\n            \"stddev\": 0.0009481889993146526\n          },\n          {\n            \"name\": \"BM_omp/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 33519619.12947797,\n            \"cpu_time\": 3398243.629032258,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0034441080361214136,\n            \"stddev\": 0.00035234063647427447\n          },\n          {\n            \"name\": \"BM_omp/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65,\n            \"real_time\": 32357082.969079223,\n            \"cpu_time\": 2257683.584615386,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.002284441162975362,\n            \"stddev\": 0.0005381978428742822\n          },\n          {\n            \"name\": \"BM_omp/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 32067964.604886416,\n            \"cpu_time\": 1977998.166666668,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0019917782981682458,\n            \"stddev\": 0.0002594533491855389\n          },\n          {\n            \"name\": \"BM_omp/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 31509286.83339082,\n            \"cpu_time\": 1423580.2121212096,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0014289448348184426,\n            \"stddev\": 0.00024200683628786132\n          },\n          {\n            \"name\": \"BM_omp/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 31543902.67228513,\n            \"cpu_time\": 1456908.6567164147,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0014654112017171374,\n            \"stddev\": 0.0003175202013289136\n          },\n          {\n            \"name\": \"BM_omp/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31239965.07287409,\n            \"cpu_time\": 1156594.4705882326,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0011585379748687368,\n            \"stddev\": 0.00020172493613242548\n          },\n          {\n            \"name\": \"BM_omp/16/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31150412.51465514,\n            \"cpu_time\": 1065149.33823529,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0010701474076246515,\n            \"stddev\": 0.00021394244925682692\n          },\n          {\n            \"name\": \"BM_omp/24/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30959615.33836089,\n            \"cpu_time\": 871033.1764705912,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0008721320910434075,\n            \"stddev\": 0.00017734576173660804\n          },\n          {\n            \"name\": \"BM_omp/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30795198.20611869,\n            \"cpu_time\": 716529.3235294109,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007148206658551798,\n            \"stddev\": 0.00023406752364358657\n          },\n          {\n            \"name\": \"BM_omp/48/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30632024.706231758,\n            \"cpu_time\": 558932.8235294102,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005571635796085876,\n            \"stddev\": 0.0002111185138909317\n          },\n          {\n            \"name\": \"BM_omp/64/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30620872.19030432,\n            \"cpu_time\": 544407.1911764716,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005425733329235192,\n            \"stddev\": 0.0002157125252829456\n          },\n          {\n            \"name\": \"BM_omp/96/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 30568353.231132463,\n            \"cpu_time\": 479132.0869565181,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0004803968822934489,\n            \"stddev\": 0.00017152748107038656\n          },\n          {\n            \"name\": \"BM_omp/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 31178996.030410584,\n            \"cpu_time\": 946393.0151515197,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0010971788221716204,\n            \"stddev\": 0.0013263504732911955\n          },\n          {\n            \"name\": \"BM_omp/192/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 35274160.516062945,\n            \"cpu_time\": 3506632.017241379,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005196523555586564,\n            \"stddev\": 0.001129020479089095\n          },\n          {\n            \"name\": \"BM_tbb/1/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 35330940.03401949,\n            \"cpu_time\": 5218861.23728813,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005253076882859282,\n            \"stddev\": 0.00036375733975781984\n          },\n          {\n            \"name\": \"BM_tbb/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 33347624.032983497,\n            \"cpu_time\": 3235708.1612903234,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.003271754322228052,\n            \"stddev\": 0.0004407854957414872\n          },\n          {\n            \"name\": \"BM_tbb/3/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 32374076.726916954,\n            \"cpu_time\": 2272832.560606064,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.002303335584601331,\n            \"stddev\": 0.00030219626468150183\n          },\n          {\n            \"name\": \"BM_tbb/4/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 32054679.605855864,\n            \"cpu_time\": 1957831.1363636316,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0019789970811512885,\n            \"stddev\": 0.00012093723597027554\n          },\n          {\n            \"name\": \"BM_tbb/6/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 31470874.726602975,\n            \"cpu_time\": 1386227.3636363575,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.001392580828079107,\n            \"stddev\": 0.00019661393735983455\n          },\n          {\n            \"name\": \"BM_tbb/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 31162876.806068998,\n            \"cpu_time\": 1080506.6567164187,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0010900893769880285,\n            \"stddev\": 0.00015122791426523257\n          },\n          {\n            \"name\": \"BM_tbb/12/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 31032934.164586686,\n            \"cpu_time\": 960364.0597014888,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0009625126023901932,\n            \"stddev\": 0.00016428339048072432\n          },\n          {\n            \"name\": \"BM_tbb/16/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30855700.08774726,\n            \"cpu_time\": 778634.4411764682,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007772091074216672,\n            \"stddev\": 0.0001812280117794162\n          },\n          {\n            \"name\": \"BM_tbb/24/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30791949.780370273,\n            \"cpu_time\": 708259.7794117691,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007049785225022145,\n            \"stddev\": 0.0002082632926585147\n          },\n          {\n            \"name\": \"BM_tbb/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 30859108.535113975,\n            \"cpu_time\": 777192.318840581,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007760430031550535,\n            \"stddev\": 0.00022144409757773707\n          },\n          {\n            \"name\": \"BM_tbb/48/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30647002.867601044,\n            \"cpu_time\": 561589.7058823555,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005585754321038942,\n            \"stddev\": 0.0002186405694567785\n          },\n          {\n            \"name\": \"BM_tbb/64/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 30711009.46407819,\n            \"cpu_time\": 617949.884057967,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0006201394017029932,\n            \"stddev\": 0.00024837536075473013\n          },\n          {\n            \"name\": \"BM_tbb/96/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30738687.3242007,\n            \"cpu_time\": 665780.338235291,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0006666529533343718,\n            \"stddev\": 0.0002578894325759036\n          },\n          {\n            \"name\": \"BM_tbb/128/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30692516.735357728,\n            \"cpu_time\": 613129.8235294112,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0006167096024214783,\n            \"stddev\": 0.00022393093238062383\n          },\n          {\n            \"name\": \"BM_tbb/192/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30671944.119282722,\n            \"cpu_time\": 594155.2647058796,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005978880628176472,\n            \"stddev\": 0.00024744018686023375\n          },\n          {\n            \"name\": \"BM_dispenso/1/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 35161656.000004224,\n            \"cpu_time\": 5022507.169491537,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005076828349571107,\n            \"stddev\": 0.0003944615478906766\n          },\n          {\n            \"name\": \"BM_dispenso/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 33066793.859688915,\n            \"cpu_time\": 2961964.53125,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.002989352746226359,\n            \"stddev\": 0.00014433565156867016\n          },\n          {\n            \"name\": \"BM_dispenso/3/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65,\n            \"real_time\": 32234470.861462448,\n            \"cpu_time\": 2137903.015384619,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0021614360336500863,\n            \"stddev\": 0.00026802577668034685\n          },\n          {\n            \"name\": \"BM_dispenso/4/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 31997484.652410176,\n            \"cpu_time\": 1905786.4696969616,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0019200499730438671,\n            \"stddev\": 0.00016553045373812584\n          },\n          {\n            \"name\": \"BM_dispenso/6/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 31623890.941420488,\n            \"cpu_time\": 1531793.9402985016,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0015436561583583035,\n            \"stddev\": 0.00021093115097096975\n          },\n          {\n            \"name\": \"BM_dispenso/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 31500270.955069963,\n            \"cpu_time\": 1415177.9104477675,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0014189618410292402,\n            \"stddev\": 0.0002672839821408429\n          },\n          {\n            \"name\": \"BM_dispenso/12/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31135224.764618803,\n            \"cpu_time\": 1045663.0735294183,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0010574554771130137,\n            \"stddev\": 0.00016839017690939981\n          },\n          {\n            \"name\": \"BM_dispenso/16/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31046610.366662636,\n            \"cpu_time\": 969178.7058823511,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0009744657624704653,\n            \"stddev\": 0.00016669616508171116\n          },\n          {\n            \"name\": \"BM_dispenso/24/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30891745.573813643,\n            \"cpu_time\": 803786.661764714,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0008113640685812296,\n            \"stddev\": 0.00018633737698669787\n          },\n          {\n            \"name\": \"BM_dispenso/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30853800.4550535,\n            \"cpu_time\": 771400.7205882268,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.000771559783435591,\n            \"stddev\": 0.00020290263680790836\n          },\n          {\n            \"name\": \"BM_dispenso/48/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30805116.38237273,\n            \"cpu_time\": 722494.4411764793,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007213208437486388,\n            \"stddev\": 0.00019749602490598935\n          },\n          {\n            \"name\": \"BM_dispenso/64/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30628888.51512552,\n            \"cpu_time\": 549314.4852941219,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005466097534415038,\n            \"stddev\": 0.00019992657492295937\n          },\n          {\n            \"name\": \"BM_dispenso/96/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30629594.57234041,\n            \"cpu_time\": 499839.3676470487,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005466979722875883,\n            \"stddev\": 0.000208215986748266\n          },\n          {\n            \"name\": \"BM_dispenso/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30545800.691470504,\n            \"cpu_time\": 437248.05882352893,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0004678638412288445,\n            \"stddev\": 0.00017982668413931877\n          },\n          {\n            \"name\": \"BM_dispenso/192/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31041808.147325784,\n            \"cpu_time\": 524161.7500000034,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0009528738549253082,\n            \"stddev\": 0.00028395565427961276\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"future_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:01:30-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/future_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            10.7002,\n            29.6816,\n            32.9683\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5860,\n            \"real_time\": 315383.3762683775,\n            \"cpu_time\": 312433.2774744027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 829,\n            \"real_time\": 2624199.9649778637,\n            \"cpu_time\": 2599321.7744270205,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102,\n            \"real_time\": 20683777.34394744,\n            \"cpu_time\": 20490668.34313725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 173624270.70038393,\n            \"cpu_time\": 100517.99999999389,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1546067071.0308478,\n            \"cpu_time\": 101421.99999929602,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 20324441333.99986,\n            \"cpu_time\": 110537.0000002992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1059,\n            \"real_time\": 1881214.0792421822,\n            \"cpu_time\": 10360.08687441024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 202,\n            \"real_time\": 10418999.524634922,\n            \"cpu_time\": 8421.549504950273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 73082731.51886232,\n            \"cpu_time\": 12975.241379293308,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2389,\n            \"real_time\": 891101.7743970414,\n            \"cpu_time\": 21027.83424026789,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 563,\n            \"real_time\": 3709310.3518395238,\n            \"cpu_time\": 29523.266429839427,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 22619541.362183843,\n            \"cpu_time\": 73561.31868131798,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5852,\n            \"real_time\": 382508.1317577007,\n            \"cpu_time\": 348837.56203007523,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1035,\n            \"real_time\": 1925946.0830548103,\n            \"cpu_time\": 1896109.8502415458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 166,\n            \"real_time\": 12806701.222827366,\n            \"cpu_time\": 11526635.28313253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6895,\n            \"real_time\": 315058.768383802,\n            \"cpu_time\": 286836.56345177646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1071,\n            \"real_time\": 1882936.0279714626,\n            \"cpu_time\": 1824981.6106442572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 166,\n            \"real_time\": 12628674.385816712,\n            \"cpu_time\": 11097613.216867467,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1674,\n            \"real_time\": 1218033.8709797652,\n            \"cpu_time\": 54056.25567502932,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 452,\n            \"real_time\": 4577371.980005925,\n            \"cpu_time\": 62798.165929201146,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73,\n            \"real_time\": 28287060.726242624,\n            \"cpu_time\": 74424.90410960974,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:02:43-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/graph_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            115.462,\n            56.7637,\n            42.0908\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_taskflow_build_big_tree\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_build_big_tree\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 719,\n            \"real_time\": 3003573.408952664,\n            \"cpu_time\": 2976054.2545201667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1188,\n            \"real_time\": 1525105.680974031,\n            \"cpu_time\": 1510754.6052188552,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1378,\n            \"real_time\": 1541630.6205106026,\n            \"cpu_time\": 1525054.0181422352,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_chain\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_chain\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47083,\n            \"real_time\": 45528.82212239234,\n            \"cpu_time\": 45052.51509037232,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_group\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_group\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4536838,\n            \"real_time\": 463.87087945716155,\n            \"cpu_time\": 459.20989618760933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100986,\n            \"real_time\": 19602.78458372719,\n            \"cpu_time\": 19412.67665815063,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114806,\n            \"real_time\": 18466.922687013728,\n            \"cpu_time\": 18284.567479051628,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 276514,\n            \"real_time\": 7736.775617154331,\n            \"cpu_time\": 7660.2829910963,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264415,\n            \"real_time\": 7873.851180787661,\n            \"cpu_time\": 7797.638677835972,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1529,\n            \"real_time\": 1384985.9745220384,\n            \"cpu_time\": 1370985.95029433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1512,\n            \"real_time\": 1420770.4933902258,\n            \"cpu_time\": 1406304.0462963758,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_scene_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:03:13-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/graph_scene_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            70.7266,\n            51.5146,\n            40.8096\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 164,\n            \"real_time\": 13178492.165113822,\n            \"cpu_time\": 10916983.878048796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 182,\n            \"real_time\": 11504798.613304457,\n            \"cpu_time\": 11173955.428571424,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_taskflow/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180,\n            \"real_time\": 11724416.132912867,\n            \"cpu_time\": 139186.88333332972,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5587,\n            \"real_time\": 374316.1036985847,\n            \"cpu_time\": 336338.19545373437,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"idle_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:03:27-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/idle_pool_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            89.6924,\n            56.2075,\n            42.4517\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83697,\n            \"real_time\": 24.1410683527769,\n            \"cpu_time\": 23.908552218120125,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.001061,\n            \"\\t1 System\": 4.099999999999937e-05\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73865,\n            \"real_time\": 26.70804280757446,\n            \"cpu_time\": 26.431217112299464,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.9052109999999995,\n            \"\\t1 System\": 8.999999999998592e-06\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74460,\n            \"real_time\": 29.046221756246997,\n            \"cpu_time\": 28.741927934461454,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 6.421445,\n            \"\\t1 System\": 5.000000000001531e-06\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75054,\n            \"real_time\": 28.256679524107906,\n            \"cpu_time\": 27.956716337570285,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 8.397722000000002,\n            \"\\t1 System\": 9.999999999975306e-07\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67147,\n            \"real_time\": 30.801611762979128,\n            \"cpu_time\": 30.50194321414211,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 12.281970000000001,\n            \"\\t1 System\": 0.006926999999999999\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52731,\n            \"real_time\": 33.88700060717647,\n            \"cpu_time\": 33.55776173408434,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 14.140971,\n            \"\\t1 System\": 0.009936\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38432,\n            \"real_time\": 55.993939556153705,\n            \"cpu_time\": 55.45277828372192,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 25.487938,\n            \"\\t1 System\": 0.11197099999999999\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_mostly_idle/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38487,\n            \"real_time\": 53.50397882457161,\n            \"cpu_time\": 52.9906788785823,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 32.45311699999999,\n            \"\\t1 System\": 0.21598499999999998\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_mostly_idle/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24269,\n            \"real_time\": 86.09150414229958,\n            \"cpu_time\": 85.19163113436885,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 48.471153999999984,\n            \"\\t1 System\": 1.178373\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_mostly_idle/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18116,\n            \"real_time\": 115.306525610755,\n            \"cpu_time\": 114.13070407374686,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 61.39823099999998,\n            \"\\t1 System\": 4.662468\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_mostly_idle/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7728,\n            \"real_time\": 266.19544332110905,\n            \"cpu_time\": 263.6586621376813,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 86.38783800000004,\n            \"\\t1 System\": 11.333889999999998\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_mostly_idle/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4733,\n            \"real_time\": 444.0785125732271,\n            \"cpu_time\": 438.8644918656246,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 115.44605499999994,\n            \"\\t1 System\": 17.488584999999997\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/96/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_mostly_idle/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2827,\n            \"real_time\": 740.871004210762,\n            \"cpu_time\": 730.7380937389464,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 168.70491600000003,\n            \"\\t1 System\": 29.679035999999996\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/128/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_mostly_idle/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2089,\n            \"real_time\": 1013.5170813942352,\n            \"cpu_time\": 1000.9232115844904,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 219.987485,\n            \"\\t1 System\": 47.661455000000004\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/192/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_mostly_idle/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1249,\n            \"real_time\": 1564.6192073498407,\n            \"cpu_time\": 1558.6541841473174,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 290.934577,\n            \"\\t1 System\": 75.44308900000001\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8473,\n            \"real_time\": 237.24057652690655,\n            \"cpu_time\": 235.0852315590698,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.991950000000088,\n            \"\\t1 System\": 0.0\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7893,\n            \"real_time\": 253.05716482169402,\n            \"cpu_time\": 250.73903167363483,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.554507000000058,\n            \"\\t1 System\": 0.40170999999998\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7689,\n            \"real_time\": 261.4750776451775,\n            \"cpu_time\": 258.89708882819656,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 5.002443999999969,\n            \"\\t1 System\": 0.9657990000000041\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7505,\n            \"real_time\": 281.04991658276157,\n            \"cpu_time\": 278.467962958028,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 6.737370000000055,\n            \"\\t1 System\": 1.6167619999999943\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4814,\n            \"real_time\": 336.2862033615493,\n            \"cpu_time\": 333.24928770253297,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 7.392745999999988,\n            \"\\t1 System\": 2.2267579999999896\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4341,\n            \"real_time\": 393.467231966217,\n            \"cpu_time\": 389.93108822851843,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 10.409781000000066,\n            \"\\t1 System\": 3.1125900000000115\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2829,\n            \"real_time\": 703.1549575823215,\n            \"cpu_time\": 696.4316104630593,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 18.35961999999995,\n            \"\\t1 System\": 5.270372000000009\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb_mostly_idle/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2133,\n            \"real_time\": 1022.7745809198034,\n            \"cpu_time\": 1013.2275513361461,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 27.26016699999991,\n            \"\\t1 System\": 7.302404999999965\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb_mostly_idle/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 994,\n            \"real_time\": 2040.8301871416104,\n            \"cpu_time\": 2019.8267857142828,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 38.986143000000084,\n            \"\\t1 System\": 9.205777000000012\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb_mostly_idle/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 840,\n            \"real_time\": 2476.697644063582,\n            \"cpu_time\": 2446.611094047626,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 53.4396999999999,\n            \"\\t1 System\": 12.414769999999976\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb_mostly_idle/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 564,\n            \"real_time\": 3656.5529715917105,\n            \"cpu_time\": 3611.7897907801494,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 80.08018900000002,\n            \"\\t1 System\": 17.804092000000026\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb_mostly_idle/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 427,\n            \"real_time\": 4945.5835292032925,\n            \"cpu_time\": 4881.2406533957865,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 109.23116299999992,\n            \"\\t1 System\": 24.218011999999987\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/96/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb_mostly_idle/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 274,\n            \"real_time\": 7870.291996183023,\n            \"cpu_time\": 7768.3328649634805,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 165.73897899999997,\n            \"\\t1 System\": 38.51627500000001\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/128/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb_mostly_idle/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 193,\n            \"real_time\": 10680.594606387762,\n            \"cpu_time\": 10542.008544041422,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 211.52255700000023,\n            \"\\t1 System\": 49.023158999999964\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/192/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb_mostly_idle/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 15888.419471281979,\n            \"cpu_time\": 15819.053885714344,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 293.6984739999998,\n            \"\\t1 System\": 80.19129699999996\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 24993.739764918977,\n            \"cpu_time\": 24786.604530864177,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.0077909999999974,\n            \"\\t1 System\": 0.0\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 25686.179948910976,\n            \"cpu_time\": 25416.3043846154,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.363712000000305,\n            \"\\t1 System\": 0.6017699999999877\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74,\n            \"real_time\": 27120.01293155088,\n            \"cpu_time\": 26856.722581081,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.7814549999998235,\n            \"\\t1 System\": 1.1826780000000099\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 27634.592146462048,\n            \"cpu_time\": 27349.955544117678,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 5.7397900000000845,\n            \"\\t1 System\": 1.6996149999999943\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 32100.157101906963,\n            \"cpu_time\": 31773.294288135512,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 8.311905999999908,\n            \"\\t1 System\": 2.9380559999999605\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57,\n            \"real_time\": 37571.71964950925,\n            \"cpu_time\": 37196.09642105257,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 12.699098000000049,\n            \"\\t1 System\": 4.262792999999988\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 71298.95682114044,\n            \"cpu_time\": 70591.28885714269,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 18.44854000000032,\n            \"\\t1 System\": 5.325367999999912\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb_mostly_idle/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 97146.88304600051,\n            \"cpu_time\": 96144.7634999999,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 26.300814999999602,\n            \"\\t1 System\": 7.539790000000039\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb_mostly_idle/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 191379.4213323854,\n            \"cpu_time\": 189764.42566666662,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 43.82737300000008,\n            \"\\t1 System\": 10.766155000000026\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb_mostly_idle/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 253836.3761268556,\n            \"cpu_time\": 251100.53625000006,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 52.12466799999993,\n            \"\\t1 System\": 12.145520999999917\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb_mostly_idle/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 379963.83500285447,\n            \"cpu_time\": 375454.293333334,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 88.35955299999978,\n            \"\\t1 System\": 19.70217200000002\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb_mostly_idle/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 492460.22501029074,\n            \"cpu_time\": 486303.72824999667,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 101.5119850000001,\n            \"\\t1 System\": 22.990192999999977\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/96/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb_mostly_idle/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 800471.5946735814,\n            \"cpu_time\": 791465.9123333319,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 184.79752700000017,\n            \"\\t1 System\": 42.67829700000004\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/128/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb_mostly_idle/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1073014.4805274904,\n            \"cpu_time\": 1062066.9599999958,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 218.22935800000005,\n            \"\\t1 System\": 52.95066600000007\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/192/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb_mostly_idle/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1533121.9850340858,\n            \"cpu_time\": 1271573.0670000056,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 197.2768460000002,\n            \"\\t1 System\": 56.288734999999974\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100084.50980586487,\n            \"cpu_time\": 13.968523809975999,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.00030399999968722113,\n            \"\\t1 System\": 6.60000000607397e-05\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100099.73704637516,\n            \"cpu_time\": 20.438857142884054,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.014020000000073196,\n            \"\\t1 System\": 0.018474999999966712\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100088.5654717595,\n            \"cpu_time\": 23.774571428838325,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.02483200000006036,\n            \"\\t1 System\": 0.03606400000001031\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100091.66628809735,\n            \"cpu_time\": 24.181952380921583,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.04112799999984418,\n            \"\\t1 System\": 0.04865299999994477\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100092.53005098019,\n            \"cpu_time\": 24.933571428472792,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.07512700000006589,\n            \"\\t1 System\": 0.07358600000009119\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100091.31337782102,\n            \"cpu_time\": 24.691333333662225,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.08434699999997974,\n            \"\\t1 System\": 0.12075600000002851\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100092.768003898,\n            \"cpu_time\": 24.821000000061066,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.10868699999991804,\n            \"\\t1 System\": 0.15461999999990894\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/16/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_very_idle/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100090.79504691597,\n            \"cpu_time\": 24.677428571283684,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.15060600000015256,\n            \"\\t1 System\": 0.2294049999999288\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/24/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_very_idle/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100091.8422415409,\n            \"cpu_time\": 25.396047618642115,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.2339710000001105,\n            \"\\t1 System\": 0.32533999999998287\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_very_idle/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100093.89442746484,\n            \"cpu_time\": 25.03609523785144,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.28244900000026973,\n            \"\\t1 System\": 0.3881580000000895\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/48/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_very_idle/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100093.6893313857,\n            \"cpu_time\": 24.87957142908012,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.4111290000000736,\n            \"\\t1 System\": 0.6274030000000721\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/64/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_very_idle/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100096.92804444404,\n            \"cpu_time\": 24.720000000332305,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.3753879999999299,\n            \"\\t1 System\": 0.5289239999999609\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/96/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_very_idle/96/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100095.84642968894,\n            \"cpu_time\": 25.069190476485694,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.7819660000000113,\n            \"\\t1 System\": 0.8930619999999863\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_very_idle/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100096.95523573707,\n            \"cpu_time\": 27.91633333336969,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.338474999999562,\n            \"\\t1 System\": 1.625312000000008\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/192/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_very_idle/192/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100098.73604645864,\n            \"cpu_time\": 24.694952380904006,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3011139999998704,\n            \"\\t1 System\": 1.593119999999999\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 336962,\n            \"real_time\": 6.090463844541889,\n            \"cpu_time\": 6.028629878146509,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.739396999999826,\n            \"\\t1 System\": 1.3192739999999503\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 358380,\n            \"real_time\": 6.661289544623591,\n            \"cpu_time\": 6.596157826887674,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.1780429999998887,\n            \"\\t1 System\": 1.545074999999997\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 407493,\n            \"real_time\": 4.612891171194431,\n            \"cpu_time\": 4.5676627819373525,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.1657539999996516,\n            \"\\t1 System\": 2.2593200000000024\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 324212,\n            \"real_time\": 6.577072088322926,\n            \"cpu_time\": 6.537046506606828,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.565743999999995,\n            \"\\t1 System\": 3.440949000000046\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 126481,\n            \"real_time\": 12.8352910872034,\n            \"cpu_time\": 12.786795534507158,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 5.552136000000246,\n            \"\\t1 System\": 3.574491999999964\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5877,\n            \"real_time\": 330.0981250610117,\n            \"cpu_time\": 328.72231972094704,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 9.914661000000251,\n            \"\\t1 System\": 4.860095000000001\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4440,\n            \"real_time\": 438.05853693393635,\n            \"cpu_time\": 436.3536797297312,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 14.337288000000171,\n            \"\\t1 System\": 5.55324399999995\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4498,\n            \"real_time\": 491.5541718654308,\n            \"cpu_time\": 489.3009933303684,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 19.15163799999982,\n            \"\\t1 System\": 5.323113999999919\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3996,\n            \"real_time\": 474.3194309281403,\n            \"cpu_time\": 472.4639789789781,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 17.648209999999835,\n            \"\\t1 System\": 3.903577999999925\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4375,\n            \"real_time\": 477.40821692028214,\n            \"cpu_time\": 475.4531837714304,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 20.27731100000028,\n            \"\\t1 System\": 3.4506659999999556\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4349,\n            \"real_time\": 471.12525384860305,\n            \"cpu_time\": 467.87364336628787,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 22.350099999999657,\n            \"\\t1 System\": 2.4520049999999856\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5713,\n            \"real_time\": 412.81347313079755,\n            \"cpu_time\": 410.92497024330305,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 27.997849999999744,\n            \"\\t1 System\": 1.9030480000000125\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/96/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_mostly_idle/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5186,\n            \"real_time\": 399.09782761893234,\n            \"cpu_time\": 397.20398688777533,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 29.6721179999995,\n            \"\\t1 System\": 0.728572999999983\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/128/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_mostly_idle/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5211,\n            \"real_time\": 407.35327768259464,\n            \"cpu_time\": 405.3849019382052,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 43.251508999999714,\n            \"\\t1 System\": 0.5368609999999308\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/192/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_mostly_idle/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4613,\n            \"real_time\": 502.5944144630782,\n            \"cpu_time\": 499.86012638196075,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 79.97183300000052,\n            \"\\t1 System\": 0.5085450000000264\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88872,\n            \"real_time\": 21.286698937246648,\n            \"cpu_time\": 21.095986857503124,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.524529000000257,\n            \"\\t1 System\": 1.2220129999999472\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90919,\n            \"real_time\": 21.071808995184323,\n            \"cpu_time\": 20.87686380184557,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.515773000000081,\n            \"\\t1 System\": 1.277311999999938\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79806,\n            \"real_time\": 24.70661612022917,\n            \"cpu_time\": 24.57379456431837,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.8915939999997136,\n            \"\\t1 System\": 1.9616000000000895\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73627,\n            \"real_time\": 26.2714674918092,\n            \"cpu_time\": 26.127909842856656,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.2927569999992556,\n            \"\\t1 System\": 2.5173509999999624\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66576,\n            \"real_time\": 32.37181714234788,\n            \"cpu_time\": 32.18647832552257,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 5.0386310000003505,\n            \"\\t1 System\": 3.8571529999999257\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 563,\n            \"real_time\": 3071.5768562537182,\n            \"cpu_time\": 3057.8423357016236,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 8.947132000000238,\n            \"\\t1 System\": 4.21333699999991\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 469,\n            \"real_time\": 4629.588424305576,\n            \"cpu_time\": 4609.603066098082,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 16.51624500000071,\n            \"\\t1 System\": 5.694422000000031\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 435,\n            \"real_time\": 4736.116423068204,\n            \"cpu_time\": 4715.931744827612,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 17.84020000000055,\n            \"\\t1 System\": 4.9337620000000015\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 472,\n            \"real_time\": 4723.002237338826,\n            \"cpu_time\": 4697.790080508429,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 20.064794000000802,\n            \"\\t1 System\": 4.742722999999955\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 419,\n            \"real_time\": 4882.209928459566,\n            \"cpu_time\": 4846.996536992814,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 20.29996899999969,\n            \"\\t1 System\": 3.2609180000000606\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 436,\n            \"real_time\": 4800.202263841713,\n            \"cpu_time\": 4768.276665137627,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 23.0100450000009,\n            \"\\t1 System\": 2.452778999999964\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 498,\n            \"real_time\": 4452.238417600832,\n            \"cpu_time\": 4423.2976184739,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 26.02731500000027,\n            \"\\t1 System\": 1.9419960000000174\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/96/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_mostly_idle/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 537,\n            \"real_time\": 3980.2945027773026,\n            \"cpu_time\": 3956.2323314711484,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 32.7218469999998,\n            \"\\t1 System\": 0.7013150000000223\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/128/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_mostly_idle/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 521,\n            \"real_time\": 4116.552756319891,\n            \"cpu_time\": 4097.568474088313,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 44.49541700000009,\n            \"\\t1 System\": 0.4938319999999976\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/192/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_mostly_idle/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 438,\n            \"real_time\": 5079.684369733821,\n            \"cpu_time\": 5054.402429223745,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 77.818937,\n            \"\\t1 System\": 0.47049300000003313\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1142,\n            \"real_time\": 1800.194836299925,\n            \"cpu_time\": 1783.8815770577933,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.6281890000000203,\n            \"\\t1 System\": 1.4507679999999255\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1169,\n            \"real_time\": 1804.6367125764132,\n            \"cpu_time\": 1786.3980367835693,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.6848540000000867,\n            \"\\t1 System\": 1.4918609999999717\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1136,\n            \"real_time\": 1825.4806751608323,\n            \"cpu_time\": 1806.7864225352266,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.662188000000242,\n            \"\\t1 System\": 1.462071999999921\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1054,\n            \"real_time\": 1841.0117675124384,\n            \"cpu_time\": 1821.985672675522,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.5227169999998296,\n            \"\\t1 System\": 1.3590750000000753\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 999,\n            \"real_time\": 1999.8306516199946,\n            \"cpu_time\": 1981.4386836836757,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.649032000000261,\n            \"\\t1 System\": 1.456103999999982\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 27330.306269844077,\n            \"cpu_time\": 27216.83615254203,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 7.876062999999704,\n            \"\\t1 System\": 3.759867999999983\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 454410.11800430715,\n            \"cpu_time\": 451206.163400002,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 17.261225000000195,\n            \"\\t1 System\": 6.048064999999951\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 484685.65923394635,\n            \"cpu_time\": 482792.58374999755,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 16.489579999999478,\n            \"\\t1 System\": 4.752347999999984\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 510501.09625793993,\n            \"cpu_time\": 508138.551750001,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 19.39972200000011,\n            \"\\t1 System\": 3.842789000000039\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 518575.38876356557,\n            \"cpu_time\": 516094.2122499961,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 21.067317000000003,\n            \"\\t1 System\": 3.1678660000000036\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 477148.31298799254,\n            \"cpu_time\": 474264.48275000154,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 21.113709999999628,\n            \"\\t1 System\": 2.2601339999999936\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 353284.20421574265,\n            \"cpu_time\": 351043.92180000443,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 21.698883000000023,\n            \"\\t1 System\": 1.2280550000000403\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/96/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_mostly_idle/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 394612.78920061886,\n            \"cpu_time\": 391916.6289999964,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 30.89940899999965,\n            \"\\t1 System\": 0.6122799999999415\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/128/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_mostly_idle/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 424057.16499779373,\n            \"cpu_time\": 422461.8354000029,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 43.777665999999954,\n            \"\\t1 System\": 0.5466339999999263\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/192/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_mostly_idle/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 508110.6572470162,\n            \"cpu_time\": 505527.1842499991,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 73.10029099999974,\n            \"\\t1 System\": 0.4642709999999397\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100106.0947088436,\n            \"cpu_time\": 11.838666667006779,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0,\n            \"\\t1 System\": 0.00030200000003333116\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100085.70019133567,\n            \"cpu_time\": 19.632333332776312,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0008760000000620494,\n            \"\\t1 System\": 0.001504999999951906\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100091.04443070966,\n            \"cpu_time\": 20.731190476551223,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0022420000004785834,\n            \"\\t1 System\": 0.0021309999999630236\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100086.6897603763,\n            \"cpu_time\": 19.33052380937148,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0011840000006486662,\n            \"\\t1 System\": 0.004345999999941341\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100092.01014015291,\n            \"cpu_time\": 22.843333333693884,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0013039999994362006,\n            \"\\t1 System\": 0.008021999999982654\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100092.20519125284,\n            \"cpu_time\": 22.560619048103295,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.004823000000214961,\n            \"\\t1 System\": 0.009165000000052714\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100089.49257566461,\n            \"cpu_time\": 18.83580952451103,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0035139999999955762,\n            \"\\t1 System\": 0.01791800000000876\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/16/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_very_idle/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100092.7007102984,\n            \"cpu_time\": 21.24742857203966,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.003642000000581902,\n            \"\\t1 System\": 0.027519999999981337\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/24/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_very_idle/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100091.80133541425,\n            \"cpu_time\": 22.32471428528914,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.02641499999936059,\n            \"\\t1 System\": 0.025900999999976193\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_very_idle/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100088.27214395361,\n            \"cpu_time\": 21.08176190469229,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.03545600000052218,\n            \"\\t1 System\": 0.04550500000004831\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/48/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_very_idle/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100087.2773306799,\n            \"cpu_time\": 20.142619048004104,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.09912600000006933,\n            \"\\t1 System\": 0.060067000000003645\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/64/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_very_idle/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100087.9612429777,\n            \"cpu_time\": 21.120333332733242,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.17547500000000582,\n            \"\\t1 System\": 0.0735140000000456\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/96/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_very_idle/96/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100087.1757610834,\n            \"cpu_time\": 19.87447619117553,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.7437929999996413,\n            \"\\t1 System\": 0.15202500000009422\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_very_idle/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100089.2536193576,\n            \"cpu_time\": 22.464333332956294,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.6097660000004907,\n            \"\\t1 System\": 0.2196320000000469\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/192/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_very_idle/192/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100087.49195618466,\n            \"cpu_time\": 19.194571428843552,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.5052969999997003,\n            \"\\t1 System\": 0.2047380000000203\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"locality_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:08:51-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/locality_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            8.63428,\n            29.2842,\n            35.1152\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4467,\n            \"real_time\": 480353.76899437245,\n            \"cpu_time\": 475409.8251623012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 19846445.63494372,\n            \"cpu_time\": 19639637.58878505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 156416370.7751924,\n            \"cpu_time\": 154734172.07692307,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3863,\n            \"real_time\": 534361.3310804078,\n            \"cpu_time\": 529036.263525757,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12909,\n            \"real_time\": 157284.85754507312,\n            \"cpu_time\": 155749.9486404833,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27367,\n            \"real_time\": 78043.87620448327,\n            \"cpu_time\": 77289.05999926924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15730,\n            \"real_time\": 133447.4162711926,\n            \"cpu_time\": 132226.42860775575,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8782,\n            \"real_time\": 239162.16897872597,\n            \"cpu_time\": 236549.64780232307,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97,\n            \"real_time\": 21772791.061444763,\n            \"cpu_time\": 21542589.237113394,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 355,\n            \"real_time\": 5690581.259042235,\n            \"cpu_time\": 5651125.05352112,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1360,\n            \"real_time\": 1669702.3227393134,\n            \"cpu_time\": 1658121.4661764712,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3056,\n            \"real_time\": 668435.1734407442,\n            \"cpu_time\": 656756.5582460737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2715,\n            \"real_time\": 774372.5856306447,\n            \"cpu_time\": 763187.1856353577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 170459606.1608754,\n            \"cpu_time\": 168584541.3333335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 84148783.33591062,\n            \"cpu_time\": 82843687.14814807,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83,\n            \"real_time\": 36167961.78372958,\n            \"cpu_time\": 35604370.54216863,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 130,\n            \"real_time\": 14011402.531132963,\n            \"cpu_time\": 13862615.123076912,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 231,\n            \"real_time\": 8495982.679905314,\n            \"cpu_time\": 8345203.316017313,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1485,\n            \"real_time\": 1439896.1380494114,\n            \"cpu_time\": 1426051.4303030313,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1561,\n            \"real_time\": 1210384.0480525761,\n            \"cpu_time\": 1203088.2876361303,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2503,\n            \"real_time\": 843992.7275303366,\n            \"cpu_time\": 840570.9444666397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5029,\n            \"real_time\": 414450.3189527502,\n            \"cpu_time\": 410947.73573274957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5981,\n            \"real_time\": 348640.0967992654,\n            \"cpu_time\": 344355.77896672953,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 24177972.943024624,\n            \"cpu_time\": 23941525.397727277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 17294070.61954581,\n            \"cpu_time\": 17171793.469026547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 249,\n            \"real_time\": 8296017.341472836,\n            \"cpu_time\": 8255325.012048177,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 366,\n            \"real_time\": 5445941.191362573,\n            \"cpu_time\": 5400739.838797802,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 408,\n            \"real_time\": 5159468.507318867,\n            \"cpu_time\": 5117355.656862757,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 177064761.9171844,\n            \"cpu_time\": 175107850.08333346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 94932420.31682959,\n            \"cpu_time\": 94180194.54545468,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 98954595.3925699,\n            \"cpu_time\": 98249126.91304323,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 75029463.62850101,\n            \"cpu_time\": 74282487.79166679,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 88977990.62348592,\n            \"cpu_time\": 87764863.75000007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3839,\n            \"real_time\": 539907.091952216,\n            \"cpu_time\": 535665.7942172438,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8221,\n            \"real_time\": 271509.64724545006,\n            \"cpu_time\": 269242.86461500934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6664,\n            \"real_time\": 344468.83403013006,\n            \"cpu_time\": 342352.49129651923,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8601,\n            \"real_time\": 227994.07928970255,\n            \"cpu_time\": 226727.38658295563,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5886,\n            \"real_time\": 303918.0292229564,\n            \"cpu_time\": 297444.50492694625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93,\n            \"real_time\": 21814113.86086976,\n            \"cpu_time\": 21549618.838709723,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102,\n            \"real_time\": 16498608.54890636,\n            \"cpu_time\": 16303002.107843062,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 164,\n            \"real_time\": 12999220.683080394,\n            \"cpu_time\": 12843724.408536525,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 300,\n            \"real_time\": 7029749.196566021,\n            \"cpu_time\": 6963892.039999991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 383,\n            \"real_time\": 5443119.798974175,\n            \"cpu_time\": 5203166.634464755,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 174024473.74964443,\n            \"cpu_time\": 172216383.08333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 95830952.2386463,\n            \"cpu_time\": 94833069.19047625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 71422076.30289097,\n            \"cpu_time\": 70728989.36666642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 77103628.03431806,\n            \"cpu_time\": 76431135.31034471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 92233525.54545271,\n            \"cpu_time\": 80345077.12500034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3687,\n            \"real_time\": 567718.7187480456,\n            \"cpu_time\": 561633.10686195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8995,\n            \"real_time\": 261377.23079859265,\n            \"cpu_time\": 258869.05636464708,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6374,\n            \"real_time\": 338593.3023187205,\n            \"cpu_time\": 335487.4185754633,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4825,\n            \"real_time\": 435125.38425296237,\n            \"cpu_time\": 430946.9181347126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2595,\n            \"real_time\": 737377.609976842,\n            \"cpu_time\": 726777.5260115605,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 21319798.693982694,\n            \"cpu_time\": 21061728.653061394,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117,\n            \"real_time\": 16379193.09338093,\n            \"cpu_time\": 16258027.81196587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 229,\n            \"real_time\": 9331350.288492136,\n            \"cpu_time\": 9270290.314410426,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 352,\n            \"real_time\": 6106910.429066788,\n            \"cpu_time\": 6043535.994318202,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 340,\n            \"real_time\": 6293437.967542559,\n            \"cpu_time\": 6191966.311764679,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 175459722.83308706,\n            \"cpu_time\": 174102192.75000098,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 103129494.2674178,\n            \"cpu_time\": 102306697.94736819,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 78476420.64526942,\n            \"cpu_time\": 77753759.64285709,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 94186897.07483819,\n            \"cpu_time\": 93118468.00000012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 87019019.08032596,\n            \"cpu_time\": 76187329.1200004,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:12:06-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/nested_for_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            23.8145,\n            28.7622,\n            33.8779\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388866,\n            \"real_time\": 5427.8580203368365,\n            \"cpu_time\": 5378.794163027882,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90,\n            \"real_time\": 18798118.90086987,\n            \"cpu_time\": 18605127.855555557,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2045379820.0469465,\n            \"cpu_time\": 2023726905.0000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108092,\n            \"real_time\": 19408.487602948073,\n            \"cpu_time\": 19190.45988602303,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 189397,\n            \"real_time\": 11423.086859705572,\n            \"cpu_time\": 11307.770144194477,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 222203,\n            \"real_time\": 9464.396425552022,\n            \"cpu_time\": 9370.828728685025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 254053,\n            \"real_time\": 7570.0686352147,\n            \"cpu_time\": 7508.7373500805,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 314949,\n            \"real_time\": 6083.302649153736,\n            \"cpu_time\": 6036.424202013654,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 318761,\n            \"real_time\": 6959.21636301693,\n            \"cpu_time\": 6906.70619053147,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 389378,\n            \"real_time\": 5547.880920465606,\n            \"cpu_time\": 5514.6168838506555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 338200,\n            \"real_time\": 5903.693436083754,\n            \"cpu_time\": 5866.168474275573,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 273837,\n            \"real_time\": 7632.124705790503,\n            \"cpu_time\": 7553.574228464371,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 239932,\n            \"real_time\": 8676.900001221455,\n            \"cpu_time\": 8640.935835986878,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187216,\n            \"real_time\": 11111.674568554647,\n            \"cpu_time\": 11033.786599435953,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 150682,\n            \"real_time\": 13896.118680423899,\n            \"cpu_time\": 13758.300633121435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101594,\n            \"real_time\": 20729.13288186201,\n            \"cpu_time\": 20428.243134437045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77971,\n            \"real_time\": 26988.242179455585,\n            \"cpu_time\": 26650.94462043583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 357,\n            \"real_time\": 6148427.24352449,\n            \"cpu_time\": 5833023.366946776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_omp/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83,\n            \"real_time\": 20174591.529957324,\n            \"cpu_time\": 19980880.096385542,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_omp/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 211,\n            \"real_time\": 8591356.78214555,\n            \"cpu_time\": 8512567.786729861,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_omp/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 328,\n            \"real_time\": 5604914.588308552,\n            \"cpu_time\": 5562246.746951225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_omp/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418,\n            \"real_time\": 4188166.375374466,\n            \"cpu_time\": 4165169.282296661,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_omp/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 616,\n            \"real_time\": 2712720.43831338,\n            \"cpu_time\": 2699838.842532467,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_omp/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 823,\n            \"real_time\": 2003284.9732587254,\n            \"cpu_time\": 1992242.5674361982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_omp/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1227,\n            \"real_time\": 1354354.0701427981,\n            \"cpu_time\": 1346785.959250196,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_omp/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2034,\n            \"real_time\": 1036697.7502444471,\n            \"cpu_time\": 1025778.4001966569,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_omp/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2994,\n            \"real_time\": 709656.8052750267,\n            \"cpu_time\": 701430.7217768846,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_omp/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3633,\n            \"real_time\": 565566.1230445926,\n            \"cpu_time\": 561074.9468758582,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_omp/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4703,\n            \"real_time\": 418497.83774902567,\n            \"cpu_time\": 413889.2715288136,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_omp/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6370,\n            \"real_time\": 344651.2053292274,\n            \"cpu_time\": 341281.42480376805,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_omp/96/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5106,\n            \"real_time\": 402554.89128871966,\n            \"cpu_time\": 395291.2424598515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_omp/128/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6749,\n            \"real_time\": 305481.05291028117,\n            \"cpu_time\": 301764.9974811087,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_omp/192/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 330,\n            \"real_time\": 6285173.4604037395,\n            \"cpu_time\": 6106619.215151497,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_omp/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2043693608.9536176,\n            \"cpu_time\": 2027766517.0000033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_omp/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1033487958.542537,\n            \"cpu_time\": 1022754865.9999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_omp/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 681079891.6655282,\n            \"cpu_time\": 674226682.666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_omp/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 519270054.99601364,\n            \"cpu_time\": 514107965.49999917,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_omp/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 348933480.1561199,\n            \"cpu_time\": 345751213.16666704,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_omp/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 263683738.87089548,\n            \"cpu_time\": 260974689.49999934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_omp/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 172630516.99652958,\n            \"cpu_time\": 171184246.33333263,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_omp/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 128004181.18422386,\n            \"cpu_time\": 126828039.2500003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_omp/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 83264280.08149378,\n            \"cpu_time\": 82502034.16666697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_omp/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 61299957.289931275,\n            \"cpu_time\": 60813346.93548372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_omp/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 41006460.20120217,\n            \"cpu_time\": 40514795.355555736,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_omp/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 32448058.111455154,\n            \"cpu_time\": 31997524.611111,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_omp/96/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 24436597.174128003,\n            \"cpu_time\": 24045322.17391298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_omp/128/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86,\n            \"real_time\": 18836969.500245135,\n            \"cpu_time\": 18597673.081395313,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_omp/192/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 28821591.787026122,\n            \"cpu_time\": 22606375.045454416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110461,\n            \"real_time\": 19470.774580758323,\n            \"cpu_time\": 19303.945836086867,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106340,\n            \"real_time\": 19643.441179284862,\n            \"cpu_time\": 19486.551777317927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115766,\n            \"real_time\": 18177.80331889066,\n            \"cpu_time\": 18004.56236718896,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111313,\n            \"real_time\": 18168.583875764067,\n            \"cpu_time\": 18009.512671475997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108187,\n            \"real_time\": 17755.20170621908,\n            \"cpu_time\": 17591.001377244822,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110883,\n            \"real_time\": 18918.508599713245,\n            \"cpu_time\": 18769.21617380485,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113596,\n            \"real_time\": 18175.45897724895,\n            \"cpu_time\": 18053.648455931638,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115643,\n            \"real_time\": 23111.17534125832,\n            \"cpu_time\": 22901.091894883353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 89604,\n            \"real_time\": 22989.976317575827,\n            \"cpu_time\": 22858.184612294008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94134,\n            \"real_time\": 22029.969426948035,\n            \"cpu_time\": 21863.028831240717,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98984,\n            \"real_time\": 21122.337256548155,\n            \"cpu_time\": 20892.354097632007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100150,\n            \"real_time\": 20395.713909219947,\n            \"cpu_time\": 20210.287928107748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 96694,\n            \"real_time\": 20607.481436736864,\n            \"cpu_time\": 20342.101981508775,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101453,\n            \"real_time\": 21075.78443250709,\n            \"cpu_time\": 20818.5063822656,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98044,\n            \"real_time\": 19042.94967516595,\n            \"cpu_time\": 18957.04991636405,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 41392151.51210212,\n            \"cpu_time\": 40973063.1333332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 18216181.196115702,\n            \"cpu_time\": 18019493.168224357,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 165,\n            \"real_time\": 12018517.332828857,\n            \"cpu_time\": 11936729.963636337,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 231,\n            \"real_time\": 8689673.16038826,\n            \"cpu_time\": 8595718.22510831,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 329,\n            \"real_time\": 5781770.771932661,\n            \"cpu_time\": 5746616.109422541,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 439,\n            \"real_time\": 4302322.209795729,\n            \"cpu_time\": 4274828.339407746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 641,\n            \"real_time\": 2903532.70683455,\n            \"cpu_time\": 2874954.1622464648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 825,\n            \"real_time\": 2264895.6060804655,\n            \"cpu_time\": 2249328.187878787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1199,\n            \"real_time\": 1526680.2910718448,\n            \"cpu_time\": 1515967.2435362632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1711,\n            \"real_time\": 1240413.203374997,\n            \"cpu_time\": 1228875.445938031,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2201,\n            \"real_time\": 937898.8904792177,\n            \"cpu_time\": 925885.6442525974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2566,\n            \"real_time\": 817992.5327060057,\n            \"cpu_time\": 806609.8168355321,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2849,\n            \"real_time\": 715947.8044910138,\n            \"cpu_time\": 702481.3320463438,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3257,\n            \"real_time\": 654133.9045039918,\n            \"cpu_time\": 643362.5747620472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3177,\n            \"real_time\": 659635.0532023926,\n            \"cpu_time\": 649772.427132509,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2353253543.0276766,\n            \"cpu_time\": 2330266601.9999948,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1171220326.0394745,\n            \"cpu_time\": 1159622301.5000079,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 792243187.3545672,\n            \"cpu_time\": 786623038.3333269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 594754630.496027,\n            \"cpu_time\": 588611655.500003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 402011654.59584445,\n            \"cpu_time\": 398636862.0000008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 304998180.71257323,\n            \"cpu_time\": 303020497.57143223,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 202880749.19953942,\n            \"cpu_time\": 200635615.80000168,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 150309982.99614742,\n            \"cpu_time\": 149214744.53846118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 98249732.62203415,\n            \"cpu_time\": 97278422.52381098,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26,\n            \"real_time\": 73168117.2306148,\n            \"cpu_time\": 72624532.23076957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 49999158.36991644,\n            \"cpu_time\": 49364809.44736918,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 38545125.50121096,\n            \"cpu_time\": 38033585.87500109,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 63,\n            \"real_time\": 28274182.681112535,\n            \"cpu_time\": 27883677.904761888,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 22709016.02643885,\n            \"cpu_time\": 22472584.013157576,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 89,\n            \"real_time\": 17846946.6856482,\n            \"cpu_time\": 17722931.134831347,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 362296,\n            \"real_time\": 5645.801767273857,\n            \"cpu_time\": 5594.415436549091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 300812,\n            \"real_time\": 6697.275165019456,\n            \"cpu_time\": 6627.369114264101,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 313009,\n            \"real_time\": 5983.401576301956,\n            \"cpu_time\": 5918.380404397377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 308145,\n            \"real_time\": 6998.933579828141,\n            \"cpu_time\": 6937.832072563201,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321588,\n            \"real_time\": 6540.57636146004,\n            \"cpu_time\": 6469.528129158991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 287822,\n            \"real_time\": 6968.777296394821,\n            \"cpu_time\": 6892.507702677425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 255624,\n            \"real_time\": 7975.769465747315,\n            \"cpu_time\": 7880.491311457513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 236705,\n            \"real_time\": 8719.130757662515,\n            \"cpu_time\": 8630.43256373982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 215860,\n            \"real_time\": 10554.474747581737,\n            \"cpu_time\": 10451.244116557034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 183169,\n            \"real_time\": 11676.441936318217,\n            \"cpu_time\": 11558.011934334014,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149841,\n            \"real_time\": 14135.132480326874,\n            \"cpu_time\": 13970.550596965993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 136581,\n            \"real_time\": 15441.503034977191,\n            \"cpu_time\": 15244.951852746834,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114844,\n            \"real_time\": 18540.012713421227,\n            \"cpu_time\": 18347.04965866747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98563,\n            \"real_time\": 21810.51120573949,\n            \"cpu_time\": 21503.228087619143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73707,\n            \"real_time\": 25836.53621835947,\n            \"cpu_time\": 21540.65012821023,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90,\n            \"real_time\": 18295488.722570654,\n            \"cpu_time\": 18119632.09999969,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 217,\n            \"real_time\": 8085964.57161593,\n            \"cpu_time\": 8007284.691244215,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 349,\n            \"real_time\": 5169146.091818681,\n            \"cpu_time\": 5115228.051575959,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 441,\n            \"real_time\": 3861745.4284945684,\n            \"cpu_time\": 3824753.394557806,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 630,\n            \"real_time\": 2542616.7619621586,\n            \"cpu_time\": 2516750.293650765,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 868,\n            \"real_time\": 1939755.0587883552,\n            \"cpu_time\": 1927619.8882488208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1240,\n            \"real_time\": 1311536.6354712376,\n            \"cpu_time\": 1300600.4112902987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2123,\n            \"real_time\": 999137.3410347536,\n            \"cpu_time\": 988526.4032030331,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3031,\n            \"real_time\": 671964.2329232227,\n            \"cpu_time\": 666926.0722533836,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3991,\n            \"real_time\": 526180.1937020954,\n            \"cpu_time\": 521581.87221248244,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5200,\n            \"real_time\": 393245.21192331583,\n            \"cpu_time\": 387631.85115384473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4741,\n            \"real_time\": 336656.9168881396,\n            \"cpu_time\": 331763.4304998902,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5513,\n            \"real_time\": 320564.0410013469,\n            \"cpu_time\": 316182.20007256285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6097,\n            \"real_time\": 336909.80793298763,\n            \"cpu_time\": 331131.0295227188,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4528,\n            \"real_time\": 452809.2592759239,\n            \"cpu_time\": 272913.3197879812,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1981087186.0245242,\n            \"cpu_time\": 1963398092.9999666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1003708317.4684085,\n            \"cpu_time\": 994237511.9999838,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 672672699.0115519,\n            \"cpu_time\": 666314960.999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 540238059.7370211,\n            \"cpu_time\": 535472462.7499934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 357161863.00851405,\n            \"cpu_time\": 354255952.8333319,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 266615783.9952835,\n            \"cpu_time\": 264223304.57142252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 177660888.66240656,\n            \"cpu_time\": 176087886.1666697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 130403514.3693909,\n            \"cpu_time\": 129005325.562499,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 84379928.54063244,\n            \"cpu_time\": 83655385.91666658,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 61954179.84417872,\n            \"cpu_time\": 61254222.43750123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 40962830.912839204,\n            \"cpu_time\": 40619288.622221775,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 31796743.073586926,\n            \"cpu_time\": 31350197.944443945,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 24255071.84751849,\n            \"cpu_time\": 23649618.930554714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77,\n            \"real_time\": 21095823.79139815,\n            \"cpu_time\": 19783591.753245566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 22355171.75080638,\n            \"cpu_time\": 14572278.720588457,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 363648,\n            \"real_time\": 5597.807451169279,\n            \"cpu_time\": 5543.2271097326275,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 238755,\n            \"real_time\": 8925.994517044994,\n            \"cpu_time\": 8825.073581705032,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 286956,\n            \"real_time\": 7254.859884432915,\n            \"cpu_time\": 7179.24418726238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 255592,\n            \"real_time\": 8367.648279078689,\n            \"cpu_time\": 8278.347655638758,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 241075,\n            \"real_time\": 8617.221487118726,\n            \"cpu_time\": 8522.000589028221,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 214793,\n            \"real_time\": 9767.221315587927,\n            \"cpu_time\": 9663.789597426437,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 196078,\n            \"real_time\": 10692.943165381585,\n            \"cpu_time\": 10612.417435918202,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176221,\n            \"real_time\": 12282.0047779982,\n            \"cpu_time\": 12209.086834146328,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161639,\n            \"real_time\": 13363.298022237064,\n            \"cpu_time\": 13248.022482197981,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160305,\n            \"real_time\": 13093.526184298362,\n            \"cpu_time\": 12955.520620068339,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 146063,\n            \"real_time\": 14876.412848865333,\n            \"cpu_time\": 14737.027303286584,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 137616,\n            \"real_time\": 15814.703355779964,\n            \"cpu_time\": 15654.989129171096,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/96/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/96/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111434,\n            \"real_time\": 18835.73648993106,\n            \"cpu_time\": 18587.507780390388,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/128/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106934,\n            \"real_time\": 19744.359661868217,\n            \"cpu_time\": 19483.66501767395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/192/10/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/192/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46830,\n            \"real_time\": 33166.106022057524,\n            \"cpu_time\": 25581.762182362003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87,\n            \"real_time\": 18617342.83906033,\n            \"cpu_time\": 18442720.96551797,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 217,\n            \"real_time\": 8082998.580672706,\n            \"cpu_time\": 8001822.230414588,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 346,\n            \"real_time\": 5187074.734218354,\n            \"cpu_time\": 5134219.933525945,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 444,\n            \"real_time\": 3887240.477336302,\n            \"cpu_time\": 3845097.4459460094,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 650,\n            \"real_time\": 2537325.3122401927,\n            \"cpu_time\": 2512655.226153828,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 852,\n            \"real_time\": 1930717.7453170673,\n            \"cpu_time\": 1911524.0446008646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1276,\n            \"real_time\": 1275296.420074976,\n            \"cpu_time\": 1260903.8691222493,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_auto/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2122,\n            \"real_time\": 970846.3025725255,\n            \"cpu_time\": 960284.0108388233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_auto/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3025,\n            \"real_time\": 674164.5266417384,\n            \"cpu_time\": 666825.6135537361,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_auto/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3969,\n            \"real_time\": 519347.1834185548,\n            \"cpu_time\": 512682.0047871237,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_auto/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5029,\n            \"real_time\": 403566.2336515359,\n            \"cpu_time\": 398182.71863192105,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_auto/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6078,\n            \"real_time\": 331786.57781965256,\n            \"cpu_time\": 327515.0742020437,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/96/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_auto/96/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6512,\n            \"real_time\": 316846.16169290437,\n            \"cpu_time\": 312705.42705774127,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_auto/128/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6184,\n            \"real_time\": 336923.16381296294,\n            \"cpu_time\": 332282.6921086597,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/192/500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_auto/192/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4868,\n            \"real_time\": 442968.65201602643,\n            \"cpu_time\": 357745.2329498731,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2007555103.9772108,\n            \"cpu_time\": 1988193299.000045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1033972073.9866607,\n            \"cpu_time\": 1024090738.0000408,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 709667346.9835272,\n            \"cpu_time\": 703679303.3333122,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 531146584.74805766,\n            \"cpu_time\": 527004613.49999726,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 360995881.1818312,\n            \"cpu_time\": 357227168.5000033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 268772764.1314268,\n            \"cpu_time\": 266326901.50000826,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 175513182.8346445,\n            \"cpu_time\": 173733183.7499975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_auto/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 131008186.62496749,\n            \"cpu_time\": 130177573.62499793,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_auto/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 84012055.95873763,\n            \"cpu_time\": 83372159.08333443,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_auto/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 62742858.32525141,\n            \"cpu_time\": 62109208.61290546,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_auto/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 42414613.09246979,\n            \"cpu_time\": 41669289.1395346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_auto/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 32646476.47123432,\n            \"cpu_time\": 31929102.924529083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/96/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_auto/96/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 23243221.820943724,\n            \"cpu_time\": 22485974.447762083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_auto/128/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110,\n            \"real_time\": 16358480.42787984,\n            \"cpu_time\": 14582942.499999842,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/192/2500/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_auto/192/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127,\n            \"real_time\": 13756457.992140057,\n            \"cpu_time\": 6322016.669291698,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:24:55-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/nested_pool_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            31.4595,\n            27.5015,\n            29.6284\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2557,\n            \"real_time\": 816.5969390066623,\n            \"cpu_time\": 808.9957125537741,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3107,\n            \"real_time\": 690.2990704983843,\n            \"cpu_time\": 683.2631770196331,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3413,\n            \"real_time\": 650.1700796941151,\n            \"cpu_time\": 644.7139238206857,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3673,\n            \"real_time\": 563.4425673823984,\n            \"cpu_time\": 558.4472891369455,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4208,\n            \"real_time\": 494.03058602355117,\n            \"cpu_time\": 489.1964389258559,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4114,\n            \"real_time\": 474.48593218175637,\n            \"cpu_time\": 470.2164783665529,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3580,\n            \"real_time\": 503.51715811876863,\n            \"cpu_time\": 498.3723427374306,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3958,\n            \"real_time\": 518.6600220013653,\n            \"cpu_time\": 513.169520717534,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3655,\n            \"real_time\": 591.3495094414734,\n            \"cpu_time\": 585.9759668946647,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3178,\n            \"real_time\": 652.7099505994678,\n            \"cpu_time\": 647.1229550031462,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3132,\n            \"real_time\": 672.6824690077553,\n            \"cpu_time\": 665.9104674329507,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1592,\n            \"real_time\": 1296.9894108132005,\n            \"cpu_time\": 1282.9310772613046,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1213,\n            \"real_time\": 1741.5401244594393,\n            \"cpu_time\": 1721.9704567188762,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 987,\n            \"real_time\": 2125.0747842950086,\n            \"cpu_time\": 2103.7456433637317,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 892,\n            \"real_time\": 2384.798213001132,\n            \"cpu_time\": 2375.8745919282514,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 25720.881506582195,\n            \"cpu_time\": 25478.229975308655,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 80,\n            \"real_time\": 26220.078737242147,\n            \"cpu_time\": 25936.683162499998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 26083.382851168237,\n            \"cpu_time\": 25797.462913580293,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 25945.654617519016,\n            \"cpu_time\": 25687.65269135798,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 25043.08612085879,\n            \"cpu_time\": 24795.53439999999,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77,\n            \"real_time\": 26753.065182355705,\n            \"cpu_time\": 26481.687025973988,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 26708.70054383538,\n            \"cpu_time\": 26464.565645569597,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83,\n            \"real_time\": 24913.667264977943,\n            \"cpu_time\": 24730.222554216816,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103,\n            \"real_time\": 20331.206776708073,\n            \"cpu_time\": 20143.188378640785,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123,\n            \"real_time\": 17217.193951648547,\n            \"cpu_time\": 17034.93368292683,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 153,\n            \"real_time\": 13423.523183126807,\n            \"cpu_time\": 13249.295947712462,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 11273.055570200086,\n            \"cpu_time\": 11131.596709677397,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 230,\n            \"real_time\": 9151.145182651184,\n            \"cpu_time\": 9027.43310434787,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 136,\n            \"real_time\": 17573.208654271988,\n            \"cpu_time\": 17352.616691176525,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 25658.422440756112,\n            \"cpu_time\": 25558.901130952312,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4135870.0200216845,\n            \"cpu_time\": 4094632.3960000086,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3886821.4320391417,\n            \"cpu_time\": 3849125.5080000004,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3583077.8679810464,\n            \"cpu_time\": 3548628.899999997,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3283223.564038053,\n            \"cpu_time\": 3251119.2280000076,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2774208.709015511,\n            \"cpu_time\": 2748042.53100001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2289450.000040233,\n            \"cpu_time\": 2266118.018,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1759098.3270201832,\n            \"cpu_time\": 1740818.5689999983,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1458545.8665387705,\n            \"cpu_time\": 1442846.8655000017,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1067574.971995782,\n            \"cpu_time\": 1055886.4864999934,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 854228.7249583751,\n            \"cpu_time\": 848153.7655000011,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 623412.1776651591,\n            \"cpu_time\": 616476.0086666661,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 499684.2445107177,\n            \"cpu_time\": 493825.2832500005,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 397035.62180511653,\n            \"cpu_time\": 392134.5947999981,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 356765.10849346715,\n            \"cpu_time\": 352293.82583333546,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 629828.5257362295,\n            \"cpu_time\": 626515.0517499975,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 179,\n            \"real_time\": 11609.584820852224,\n            \"cpu_time\": 42.56218994415276,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 165,\n            \"real_time\": 14861.299618231978,\n            \"cpu_time\": 53.49112121211185,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 23260.45064136195,\n            \"cpu_time\": 92.50782051285802,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103,\n            \"real_time\": 19918.908203445666,\n            \"cpu_time\": 99.3516019417429,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106,\n            \"real_time\": 17536.250349432932,\n            \"cpu_time\": 207.12301886787353,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 128,\n            \"real_time\": 13647.330984895234,\n            \"cpu_time\": 240.66099999997536,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 183,\n            \"real_time\": 11475.700142035068,\n            \"cpu_time\": 130.58952459018371,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 225,\n            \"real_time\": 8879.341666276256,\n            \"cpu_time\": 157.89895111115334,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 293,\n            \"real_time\": 6995.249191162402,\n            \"cpu_time\": 182.05176109218368,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 329,\n            \"real_time\": 6090.916638364478,\n            \"cpu_time\": 106.11675075985845,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 382,\n            \"real_time\": 5238.977497375292,\n            \"cpu_time\": 149.33942146594583,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 427,\n            \"real_time\": 4849.148360768058,\n            \"cpu_time\": 129.34088524592565,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 456,\n            \"real_time\": 4463.851098543066,\n            \"cpu_time\": 131.3767872807073,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 476,\n            \"real_time\": 4331.044172339862,\n            \"cpu_time\": 119.56745168066642,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 473,\n            \"real_time\": 4351.2304969639945,\n            \"cpu_time\": 129.00362579281818,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 450063.94078955054,\n            \"cpu_time\": 312.5569999980371,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 515094.5247441996,\n            \"cpu_time\": 254.23625000087213,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 329381.84160739183,\n            \"cpu_time\": 176.73099999910846,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 273963.1469982366,\n            \"cpu_time\": 174.75716666837116,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 290061.0505769561,\n            \"cpu_time\": 327.8735714279232,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_folly/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 310126.4443685068,\n            \"cpu_time\": 402.73325000050875,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_folly/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 279716.8006654829,\n            \"cpu_time\": 644.293833332199,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_folly/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 231524.91728043449,\n            \"cpu_time\": 667.9754285719192,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_folly/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 198706.03650342673,\n            \"cpu_time\": 904.8280000001796,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_folly/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 169625.51966814013,\n            \"cpu_time\": 975.4139999991197,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_folly/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 141459.9449975261,\n            \"cpu_time\": 1052.644749999369,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_folly/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 128411.01668891497,\n            \"cpu_time\": 1070.6315625004236,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_folly/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 118215.85717067744,\n            \"cpu_time\": 1140.594888889426,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_folly/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 112419.9654747683,\n            \"cpu_time\": 1095.88147368437,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_folly/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 106952.27314718068,\n            \"cpu_time\": 1236.690249999839,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_folly/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_folly/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_folly/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_folly/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_folly/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_folly/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_folly/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_folly/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_folly/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_folly/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_folly/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_folly/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_folly/96/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_folly/128/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_folly/192/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3739,\n            \"real_time\": 561.5110823938907,\n            \"cpu_time\": 556.0428133190691,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9572,\n            \"real_time\": 214.23315263771275,\n            \"cpu_time\": 212.12276661094904,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7132,\n            \"real_time\": 266.32617216633525,\n            \"cpu_time\": 263.8601634885035,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8922,\n            \"real_time\": 220.0736441399808,\n            \"cpu_time\": 217.89592423223624,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8929,\n            \"real_time\": 255.39535468784047,\n            \"cpu_time\": 253.3313085451897,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5830,\n            \"real_time\": 263.3105888587341,\n            \"cpu_time\": 260.8660015437415,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4014,\n            \"real_time\": 491.48015493474156,\n            \"cpu_time\": 486.31872047832985,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3277,\n            \"real_time\": 598.8224601639656,\n            \"cpu_time\": 593.2565764418727,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2548,\n            \"real_time\": 786.0636636665971,\n            \"cpu_time\": 780.2290855572971,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1905,\n            \"real_time\": 790.5374640437561,\n            \"cpu_time\": 786.5525296587929,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1047,\n            \"real_time\": 1788.9931041003697,\n            \"cpu_time\": 1771.0673772683801,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1804.3723900336772,\n            \"cpu_time\": 1789.3985299999997,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1086,\n            \"real_time\": 2200.3241039857157,\n            \"cpu_time\": 2175.605238489857,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 895,\n            \"real_time\": 2604.70770052296,\n            \"cpu_time\": 2580.4213698324234,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 761,\n            \"real_time\": 2675.0122259692844,\n            \"cpu_time\": 2633.8760433639973,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 153,\n            \"real_time\": 13906.27705875565,\n            \"cpu_time\": 13745.602457516337,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 462,\n            \"real_time\": 3288.549179557985,\n            \"cpu_time\": 3247.645675324677,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388,\n            \"real_time\": 5577.736401860842,\n            \"cpu_time\": 5525.879262886616,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370,\n            \"real_time\": 6430.39589175149,\n            \"cpu_time\": 6370.274067567582,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 303,\n            \"real_time\": 5439.549300315553,\n            \"cpu_time\": 5389.229392739251,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 369,\n            \"real_time\": 5445.129815728825,\n            \"cpu_time\": 5400.355317073175,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 423,\n            \"real_time\": 5246.521314456354,\n            \"cpu_time\": 5195.226593380659,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 326,\n            \"real_time\": 6409.3522638928125,\n            \"cpu_time\": 6358.6307300613535,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 236,\n            \"real_time\": 9556.114627245688,\n            \"cpu_time\": 9495.631995762718,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 240,\n            \"real_time\": 9727.944937670449,\n            \"cpu_time\": 9667.34431250001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 19832.651170436293,\n            \"cpu_time\": 19722.706639999786,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 16602.82329775076,\n            \"cpu_time\": 16466.625223404088,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77,\n            \"real_time\": 24029.753790781288,\n            \"cpu_time\": 23762.269428571446,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 95,\n            \"real_time\": 26208.495115861297,\n            \"cpu_time\": 25874.03396842122,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 28785.290499516308,\n            \"cpu_time\": 28451.014871795,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2173924.262984656,\n            \"cpu_time\": 2156555.6619999884,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 169642.42554439063,\n            \"cpu_time\": 167788.8757272709,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 319893.1255028583,\n            \"cpu_time\": 316696.2470000006,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 580504.3373644972,\n            \"cpu_time\": 575842.3730000004,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 556944.4946401442,\n            \"cpu_time\": 552353.7656666709,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 754006.3100168481,\n            \"cpu_time\": 748735.3793333397,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 547277.9212577734,\n            \"cpu_time\": 542167.5367500001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 481394.80319805443,\n            \"cpu_time\": 478402.34119999537,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 341403.3738275369,\n            \"cpu_time\": 338778.5111666659,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 263397.59925031103,\n            \"cpu_time\": 260740.92087500135,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 345024.1790075476,\n            \"cpu_time\": 341169.24116666784,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 484914.2519989982,\n            \"cpu_time\": 479072.2232000007,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 691314.4426653162,\n            \"cpu_time\": 682057.0326666579,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 782094.419002533,\n            \"cpu_time\": 771350.8413333348,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 634940.2366516491,\n            \"cpu_time\": 623837.9143333266,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19213,\n            \"real_time\": 111.65777588218461,\n            \"cpu_time\": 110.50088159058969,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11486,\n            \"real_time\": 167.29135051716378,\n            \"cpu_time\": 165.7152928782865,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14873,\n            \"real_time\": 140.260770585813,\n            \"cpu_time\": 138.8846322194593,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13864,\n            \"real_time\": 142.4424644339689,\n            \"cpu_time\": 141.02427257645618,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21051,\n            \"real_time\": 109.83408441116131,\n            \"cpu_time\": 108.81114502874091,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19768,\n            \"real_time\": 95.79625733689345,\n            \"cpu_time\": 94.85108898219187,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12860,\n            \"real_time\": 169.36375357610396,\n            \"cpu_time\": 167.8141041990652,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10895,\n            \"real_time\": 141.54544873133185,\n            \"cpu_time\": 140.14532739788547,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10875,\n            \"real_time\": 156.68389508393648,\n            \"cpu_time\": 155.47697048276305,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12483,\n            \"real_time\": 191.29878418280006,\n            \"cpu_time\": 189.67768332932454,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10271,\n            \"real_time\": 195.9300837288661,\n            \"cpu_time\": 194.1636900009725,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11223,\n            \"real_time\": 175.70291053655444,\n            \"cpu_time\": 174.0501858683033,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10110,\n            \"real_time\": 192.37952730383515,\n            \"cpu_time\": 190.31166815035104,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10558,\n            \"real_time\": 215.78623763888757,\n            \"cpu_time\": 213.2610588179596,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7707,\n            \"real_time\": 291.9531694563973,\n            \"cpu_time\": 243.23985130401113,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 620,\n            \"real_time\": 3359.2989660739418,\n            \"cpu_time\": 3328.5372709677345,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 786,\n            \"real_time\": 2588.6582824136144,\n            \"cpu_time\": 2563.2044262086324,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 700,\n            \"real_time\": 2538.561227099438,\n            \"cpu_time\": 2513.1478499999307,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 600,\n            \"real_time\": 3228.1607765859612,\n            \"cpu_time\": 3208.750396666744,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 966,\n            \"real_time\": 1825.1060094109757,\n            \"cpu_time\": 1808.1552380952376,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 722,\n            \"real_time\": 2622.078020813155,\n            \"cpu_time\": 2605.9237853185864,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 939,\n            \"real_time\": 2022.2084334415717,\n            \"cpu_time\": 2006.3829435569705,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1172,\n            \"real_time\": 1378.006859163598,\n            \"cpu_time\": 1366.175880546095,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1292,\n            \"real_time\": 1703.3984296055562,\n            \"cpu_time\": 1689.0853018575845,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1306,\n            \"real_time\": 1627.6237450020922,\n            \"cpu_time\": 1615.5292695252454,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1141,\n            \"real_time\": 1908.9737624431145,\n            \"cpu_time\": 1891.148898334795,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1148,\n            \"real_time\": 1910.2322587902408,\n            \"cpu_time\": 1897.3146149825604,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_bulk/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1204,\n            \"real_time\": 1694.7716843503902,\n            \"cpu_time\": 1682.6662782392154,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_bulk/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1798,\n            \"real_time\": 1027.0844538047604,\n            \"cpu_time\": 1018.4883331479192,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_bulk/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 984,\n            \"real_time\": 1993.8776229803518,\n            \"cpu_time\": 1947.9100467479977,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 553279.7162595671,\n            \"cpu_time\": 547842.8962500033,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 185155.28640709817,\n            \"cpu_time\": 183454.7523000026,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 190434.54029597342,\n            \"cpu_time\": 188377.2377000014,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 211162.30763833632,\n            \"cpu_time\": 209357.81899999545,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 186047.321905128,\n            \"cpu_time\": 184455.7979090899,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 191267.06270035356,\n            \"cpu_time\": 189784.95430000065,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 143009.98845674956,\n            \"cpu_time\": 142025.0975384647,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_bulk/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 127544.1037655315,\n            \"cpu_time\": 126478.87676470593,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_bulk/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 82652.85904607957,\n            \"cpu_time\": 82123.07661904648,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_bulk/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 53943.43257955227,\n            \"cpu_time\": 53510.39447368509,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_bulk/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 49439.21600116065,\n            \"cpu_time\": 48986.45351351348,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_bulk/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 57706.742242255525,\n            \"cpu_time\": 57137.24964864868,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_bulk/96/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 41295.12085055467,\n            \"cpu_time\": 40855.31755000034,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_bulk/128/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 54539.696852926434,\n            \"cpu_time\": 53980.34975609829,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_bulk/192/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 56159.7689998169,\n            \"cpu_time\": 55679.01474359051,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"once_function_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:32:18-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/once_function_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            57.3027,\n            42.7261,\n            35.6768\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_move_std_function<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23808834,\n            \"real_time\": 90.22610574064771,\n            \"cpu_time\": 89.367340500589,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kSmallSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 118773852,\n            \"real_time\": 18.200115813128075,\n            \"cpu_time\": 18.03554094549363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kMediumSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21815838,\n            \"real_time\": 98.04443936580248,\n            \"cpu_time\": 97.07727871833302,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kMediumSize>\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 162472093,\n            \"real_time\": 12.675758420414196,\n            \"cpu_time\": 12.540839656691064,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kLargeSize>\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22108637,\n            \"real_time\": 94.82982284240283,\n            \"cpu_time\": 93.90342367102957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kLargeSize>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 165326238,\n            \"real_time\": 12.52188034427126,\n            \"cpu_time\": 12.397111999850855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20308717,\n            \"real_time\": 103.33237633815814,\n            \"cpu_time\": 102.35555525245627,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64845044,\n            \"real_time\": 32.45897671057875,\n            \"cpu_time\": 32.1913679632942,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2103879,\n            \"real_time\": 1027.143109470045,\n            \"cpu_time\": 1017.4279490407952,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kSmallSize>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 627468,\n            \"real_time\": 3361.821626088938,\n            \"cpu_time\": 3330.657641505222,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kSmallSize>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 754043,\n            \"real_time\": 2801.8524209845837,\n            \"cpu_time\": 2774.3337488710895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1151717,\n            \"real_time\": 1804.8427053006515,\n            \"cpu_time\": 1787.6533219532212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kMediumSize>\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 601120,\n            \"real_time\": 3543.9121156492406,\n            \"cpu_time\": 3510.3853456880447,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kMediumSize>\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 725543,\n            \"real_time\": 2971.3241144936474,\n            \"cpu_time\": 2941.5337312881543,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 687849,\n            \"real_time\": 3035.8301109637937,\n            \"cpu_time\": 3006.302091011252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kLargeSize>\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 437288,\n            \"real_time\": 4914.103515310017,\n            \"cpu_time\": 4865.072178975862,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kLargeSize>\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 616156,\n            \"real_time\": 3446.682486087839,\n            \"cpu_time\": 3414.854830594853,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 233267,\n            \"real_time\": 8985.298515959676,\n            \"cpu_time\": 8895.561425319498,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 296605,\n            \"real_time\": 6987.662335701662,\n            \"cpu_time\": 6917.517135584379,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321096,\n            \"real_time\": 6576.404779099659,\n            \"cpu_time\": 6513.889874056355,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pipeline_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:33:15-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/pipeline_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            24.0415,\n            35.8721,\n            33.7368\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 187840995.17771128,\n            \"cpu_time\": 186309662.27272728,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 119103590.2269909,\n            \"cpu_time\": 35720952.33333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 166112452.5940977,\n            \"cpu_time\": 153797189.99999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 120492782.23147506,\n            \"cpu_time\": 148229.7647058735,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_par/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 451,\n            \"real_time\": 4583813.634157973,\n            \"cpu_time\": 942132.4567627513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_par/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 486,\n            \"real_time\": 4369178.378701578,\n            \"cpu_time\": 4325472.3559670765,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow_par/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 67558199.37825435,\n            \"cpu_time\": 138724.53125002293,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pool_allocator_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:33:34-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/pool_allocator_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            33.1187,\n            37.0737,\n            34.1709\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 720,\n            \"real_time\": 2975919.9347204734,\n            \"cpu_time\": 2945243.738888889,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 152,\n            \"real_time\": 14348658.203839716,\n            \"cpu_time\": 14206345.15131579,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49805,\n            \"real_time\": 41829.69655771653,\n            \"cpu_time\": 41429.041903423364,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11849,\n            \"real_time\": 168008.74613465345,\n            \"cpu_time\": 166407.90387374457,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59362,\n            \"real_time\": 33794.848673860324,\n            \"cpu_time\": 33438.827987601486,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16110,\n            \"real_time\": 127849.54264510277,\n            \"cpu_time\": 126596.51688392299,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 13254944.664593901,\n            \"cpu_time\": 13109526.416149057,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 57140856.40549357,\n            \"cpu_time\": 56540248.97297301,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56413,\n            \"real_time\": 35292.99994628807,\n            \"cpu_time\": 34967.114228989754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14940,\n            \"real_time\": 143401.5512679625,\n            \"cpu_time\": 141908.9246318609,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69652,\n            \"real_time\": 30056.156463357773,\n            \"cpu_time\": 29769.902989146038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17552,\n            \"real_time\": 123024.96302838938,\n            \"cpu_time\": 121861.13400182319,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 17332000.604402572,\n            \"cpu_time\": 17086223.629032273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 76420053.44628003,\n            \"cpu_time\": 75511598.37931047,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55496,\n            \"real_time\": 37197.92132828996,\n            \"cpu_time\": 36838.585844024725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12997,\n            \"real_time\": 166955.776410512,\n            \"cpu_time\": 165315.65284296378,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65673,\n            \"real_time\": 32402.068932969254,\n            \"cpu_time\": 32070.661900628867,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16778,\n            \"real_time\": 129539.98187919,\n            \"cpu_time\": 128159.56037668386,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90877,\n            \"real_time\": 22772.6631609868,\n            \"cpu_time\": 22535.253606523085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23207,\n            \"real_time\": 91573.88395439883,\n            \"cpu_time\": 90695.97897186199,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113682,\n            \"real_time\": 19129.843871014305,\n            \"cpu_time\": 18961.00865572387,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27391,\n            \"real_time\": 76020.71056192703,\n            \"cpu_time\": 75279.94001679377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91332,\n            \"real_time\": 24500.514847263847,\n            \"cpu_time\": 24260.763456400782,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21902,\n            \"real_time\": 93817.99278311372,\n            \"cpu_time\": 92919.5760661125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111313,\n            \"real_time\": 18869.79938539505,\n            \"cpu_time\": 18680.792486052796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28116,\n            \"real_time\": 77850.0221602829,\n            \"cpu_time\": 77047.65770379861,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92589,\n            \"real_time\": 24446.957975564914,\n            \"cpu_time\": 24206.85626802322,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21497,\n            \"real_time\": 93475.17965490145,\n            \"cpu_time\": 92546.9846025025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112118,\n            \"real_time\": 18986.34414661028,\n            \"cpu_time\": 18793.758656058784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26455,\n            \"real_time\": 79856.03349275241,\n            \"cpu_time\": 79108.15131355147,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 641,\n            \"real_time\": 3282233.900150833,\n            \"cpu_time\": 3250158.5101404125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 138,\n            \"real_time\": 15278250.93480583,\n            \"cpu_time\": 15115516.67391298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 160791.86840215698,\n            \"cpu_time\": 159312.92369999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3977,\n            \"real_time\": 577326.7867842158,\n            \"cpu_time\": 572278.7005280381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 152,\n            \"real_time\": 14093878.28913934,\n            \"cpu_time\": 13924574.61184212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 55199268.77847562,\n            \"cpu_time\": 54601113.63888881,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14028,\n            \"real_time\": 179931.52002981378,\n            \"cpu_time\": 178391.6127744512,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3764,\n            \"real_time\": 584039.71492299,\n            \"cpu_time\": 579161.0547290116,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 18578763.810219243,\n            \"cpu_time\": 17688453.709999975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 104357349.50006008,\n            \"cpu_time\": 102983835.44999936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13564,\n            \"real_time\": 142368.2185179389,\n            \"cpu_time\": 140963.03546151612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3533,\n            \"real_time\": 584453.8737662578,\n            \"cpu_time\": 579017.6048683835,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 514,\n            \"real_time\": 4166962.9999356717,\n            \"cpu_time\": 4127856.9416342364,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 118,\n            \"real_time\": 17835011.796520676,\n            \"cpu_time\": 17647068.627118614,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 498,\n            \"real_time\": 3337312.323306818,\n            \"cpu_time\": 3311129.8835341316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 120,\n            \"real_time\": 18312848.72508453,\n            \"cpu_time\": 18205555.658333357,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 128,\n            \"real_time\": 15078477.054885298,\n            \"cpu_time\": 14941666.28906246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 54511617.81705818,\n            \"cpu_time\": 54044452.157894716,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 453,\n            \"real_time\": 4539657.997843248,\n            \"cpu_time\": 4508837.260485624,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 136,\n            \"real_time\": 19361157.389700085,\n            \"cpu_time\": 19246038.713235315,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 45885539.51078549,\n            \"cpu_time\": 44448430.95348865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 396402581.49787164,\n            \"cpu_time\": 393217006.6666648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 452,\n            \"real_time\": 4387526.597263111,\n            \"cpu_time\": 4362062.734513259,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86,\n            \"real_time\": 19438887.744611345,\n            \"cpu_time\": 19314790.91860451,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 473,\n            \"real_time\": 4450289.575121194,\n            \"cpu_time\": 4417203.0591965895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103,\n            \"real_time\": 19171191.3692557,\n            \"cpu_time\": 19030045.262135815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 33040409.303688698,\n            \"cpu_time\": 32868009.13043445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 141298952.00200665,\n            \"cpu_time\": 140574830.00000012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127,\n            \"real_time\": 16726744.26772287,\n            \"cpu_time\": 16586183.464566851,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 56956960.973833255,\n            \"cpu_time\": 56524271.459459126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 31212321.33707963,\n            \"cpu_time\": 31032936.455882184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 135157251.50500658,\n            \"cpu_time\": 134310330.7499991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 95670608.75027286,\n            \"cpu_time\": 90226984.16666585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 875061692.4953647,\n            \"cpu_time\": 864340090.4999936,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 34722476.0013793,\n            \"cpu_time\": 34529578.18965554,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 174422600.78516686,\n            \"cpu_time\": 173220625.33333513,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"rw_lock_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:36:34-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/rw_lock_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            10.2012,\n            22.9292,\n            29.0811\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7137,\n            \"real_time\": 302898.2279790129,\n            \"cpu_time\": 300216.6782962029,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6552,\n            \"real_time\": 321741.76084413845,\n            \"cpu_time\": 318866.6422466423,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6683,\n            \"real_time\": 339963.1092224516,\n            \"cpu_time\": 336376.0848421368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6820,\n            \"real_time\": 305530.71656198817,\n            \"cpu_time\": 302566.7529325513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8647,\n            \"real_time\": 234241.11761073474,\n            \"cpu_time\": 231765.03134034926,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 298,\n            \"real_time\": 6986149.140999297,\n            \"cpu_time\": 6907578.879194634,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 364,\n            \"real_time\": 5735710.994366066,\n            \"cpu_time\": 5677567.3241758235,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 386,\n            \"real_time\": 5424167.795307027,\n            \"cpu_time\": 5371657.582901547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 5476145.517391463,\n            \"cpu_time\": 5420475.9120000005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 389,\n            \"real_time\": 5357427.603941037,\n            \"cpu_time\": 5303152.460154246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 609,\n            \"real_time\": 3485600.331573394,\n            \"cpu_time\": 3450794.4515599287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 596,\n            \"real_time\": 3487103.6946639144,\n            \"cpu_time\": 3450254.1359060383,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 586,\n            \"real_time\": 3487332.4675634885,\n            \"cpu_time\": 3452171.4539249074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 597,\n            \"real_time\": 3493424.1557493806,\n            \"cpu_time\": 3460749.336683413,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 603,\n            \"real_time\": 3463243.933589156,\n            \"cpu_time\": 3429617.9618573748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 306,\n            \"real_time\": 6879518.196227187,\n            \"cpu_time\": 6813402.777777783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 71866493.78854781,\n            \"cpu_time\": 68354871.53571431,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 167318594.00169924,\n            \"cpu_time\": 86000753.08333288,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 341148277.99688405,\n            \"cpu_time\": 104271116.33333297,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 677657012.323228,\n            \"cpu_time\": 105234778.99999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1352303583.9898512,\n            \"cpu_time\": 111762926.00000082,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 349,\n            \"real_time\": 5951811.882392383,\n            \"cpu_time\": 5896462.856733539,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 115266769.44534606,\n            \"cpu_time\": 89894137.05555588,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 341040573.9975561,\n            \"cpu_time\": 158293300.00000092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 580087924.337325,\n            \"cpu_time\": 167796793.33333302,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1217093817.0165756,\n            \"cpu_time\": 401011086.0000005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2481908222.078346,\n            \"cpu_time\": 204796371.99999702,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 368,\n            \"real_time\": 5439939.5951844305,\n            \"cpu_time\": 5385150.5543478215,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 108378071.25062683,\n            \"cpu_time\": 76447088.69999981,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 310903409.8451957,\n            \"cpu_time\": 145972527.0000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 887331245.0014054,\n            \"cpu_time\": 274109744.0000004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2087598671.0889266,\n            \"cpu_time\": 250165195.000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4436426979.955286,\n            \"cpu_time\": 791947821.9999974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 404,\n            \"real_time\": 5272600.472741068,\n            \"cpu_time\": 5224836.839108911,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 70298664.95513883,\n            \"cpu_time\": 48570622.260869004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 213834074.64335588,\n            \"cpu_time\": 96449829.45454603,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 482531272.3405659,\n            \"cpu_time\": 128105148.50000013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1080140528.5019426,\n            \"cpu_time\": 166671073.9999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2182503418.0656075,\n            \"cpu_time\": 288442493.9999946,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418,\n            \"real_time\": 5083712.509668401,\n            \"cpu_time\": 5032738.67464115,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 31957196.472730074,\n            \"cpu_time\": 26174849.055555586,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 81975506.10984088,\n            \"cpu_time\": 57832362.37037039,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 220818660.00209832,\n            \"cpu_time\": 107122599.88888997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 447109856.759198,\n            \"cpu_time\": 109446369.74999966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 836072857.3364515,\n            \"cpu_time\": 93196583.99999754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 565,\n            \"real_time\": 3700086.488429688,\n            \"cpu_time\": 3663051.141592932,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60,\n            \"real_time\": 28392350.266221914,\n            \"cpu_time\": 28136411.916666523,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 133017257.26729879,\n            \"cpu_time\": 131967607.46666692,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 508057433.99541825,\n            \"cpu_time\": 504347667.9999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2760446025.9899497,\n            \"cpu_time\": 2750920006.0000014,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 9022123825.037851,\n            \"cpu_time\": 8947394693.000008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 574,\n            \"real_time\": 3720033.916284554,\n            \"cpu_time\": 3690767.7421602737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 29537342.013266515,\n            \"cpu_time\": 29399313.1971832,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 112291602.57713182,\n            \"cpu_time\": 111825059.3157895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 349326075.1944035,\n            \"cpu_time\": 347836337.80000114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1204738817.526959,\n            \"cpu_time\": 1199941004.4999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3991187106.0030537,\n            \"cpu_time\": 3965838927.9999967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 535,\n            \"real_time\": 3664471.061734883,\n            \"cpu_time\": 3621378.5457943855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 20912511.30629217,\n            \"cpu_time\": 20729904.438775465,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 60963214.51266042,\n            \"cpu_time\": 60459881.909090646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 187014475.99839106,\n            \"cpu_time\": 185834493.083334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 591411885.6502076,\n            \"cpu_time\": 588287564.0000027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1940640599.001199,\n            \"cpu_time\": 1919230553.999995,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 565,\n            \"real_time\": 3696541.874298611,\n            \"cpu_time\": 3651792.467256661,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131,\n            \"real_time\": 15678133.679560976,\n            \"cpu_time\": 15528147.36641213,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 43702080.71676366,\n            \"cpu_time\": 43388178.04347852,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 106150809.05048862,\n            \"cpu_time\": 105457471.52631621,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 293041637.001027,\n            \"cpu_time\": 290652035.14285743,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 877953816.4963014,\n            \"cpu_time\": 873629618.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 561,\n            \"real_time\": 3729210.1123302164,\n            \"cpu_time\": 3689839.035650662,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 146,\n            \"real_time\": 14379766.992969465,\n            \"cpu_time\": 14274084.136986304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60,\n            \"real_time\": 34453917.16668382,\n            \"cpu_time\": 34196698.21666673,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 80204004.19831276,\n            \"cpu_time\": 79687162.6799998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 194945967.50009805,\n            \"cpu_time\": 193819910.70000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 482794601.6099304,\n            \"cpu_time\": 479725596.3999988,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:40:04-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/simple_for_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            9.74854,\n            15.1763,\n            24.6289\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14846989,\n            \"real_time\": 145.1576499406187,\n            \"cpu_time\": 143.90739570157962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14255,\n            \"real_time\": 148426.6688174368,\n            \"cpu_time\": 147355.00589266923,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 63,\n            \"real_time\": 24937919.827015508,\n            \"cpu_time\": 24736828.11111111,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2491896,\n            \"real_time\": 832.4648379903613,\n            \"cpu_time\": 825.12399755046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1427890,\n            \"real_time\": 1467.2887715688491,\n            \"cpu_time\": 1451.887445111319,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1253031,\n            \"real_time\": 1500.7217809578617,\n            \"cpu_time\": 1484.973148309979,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1161459,\n            \"real_time\": 1486.78320627105,\n            \"cpu_time\": 1470.6797364349504,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1072041,\n            \"real_time\": 1453.226355112451,\n            \"cpu_time\": 1439.4383890168372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 885121,\n            \"real_time\": 2514.4078403804365,\n            \"cpu_time\": 2492.450194945097,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 652935,\n            \"real_time\": 3067.598129856155,\n            \"cpu_time\": 3040.139393660927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 506858,\n            \"real_time\": 4235.101146729439,\n            \"cpu_time\": 4197.0250740838665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 335493,\n            \"real_time\": 6169.035169282156,\n            \"cpu_time\": 6114.240779986474,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 278881,\n            \"real_time\": 7451.089281800264,\n            \"cpu_time\": 7367.941781620122,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 216840,\n            \"real_time\": 9674.570891217429,\n            \"cpu_time\": 9582.73347168419,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 168144,\n            \"real_time\": 12519.62525619168,\n            \"cpu_time\": 12397.667213816725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115545,\n            \"real_time\": 17646.232039260907,\n            \"cpu_time\": 17457.03627158253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93905,\n            \"real_time\": 22076.28717305528,\n            \"cpu_time\": 21861.645716415558,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 329,\n            \"real_time\": 6428535.765823894,\n            \"cpu_time\": 5669532.273556222,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_omp/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14693,\n            \"real_time\": 144641.39494751344,\n            \"cpu_time\": 143506.09875450906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_omp/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27532,\n            \"real_time\": 75915.22145009942,\n            \"cpu_time\": 75174.97835246245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_omp/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39769,\n            \"real_time\": 54520.801253825324,\n            \"cpu_time\": 53971.849732203395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_omp/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49905,\n            \"real_time\": 41325.43440433061,\n            \"cpu_time\": 40938.889089269665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_omp/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70219,\n            \"real_time\": 29213.35921850156,\n            \"cpu_time\": 28892.42022814337,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_omp/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90233,\n            \"real_time\": 23412.237352729913,\n            \"cpu_time\": 23169.04229051454,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_omp/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127816,\n            \"real_time\": 18878.962594416003,\n            \"cpu_time\": 18680.063481880195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_omp/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 145906,\n            \"real_time\": 14503.1855097176,\n            \"cpu_time\": 14348.510068126072,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_omp/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 165349,\n            \"real_time\": 12623.428493121623,\n            \"cpu_time\": 12494.663324241516,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_omp/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 168234,\n            \"real_time\": 12976.136910789395,\n            \"cpu_time\": 12828.415147948688,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_omp/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154419,\n            \"real_time\": 13527.269325258048,\n            \"cpu_time\": 13379.326106243374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_omp/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 134246,\n            \"real_time\": 15592.475089923177,\n            \"cpu_time\": 15398.312381746922,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_omp/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 96876,\n            \"real_time\": 21633.21891987572,\n            \"cpu_time\": 21271.34527643588,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_omp/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77546,\n            \"real_time\": 26753.703492930174,\n            \"cpu_time\": 26359.33730946787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_omp/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 347,\n            \"real_time\": 6562273.815523844,\n            \"cpu_time\": 5897006.927953908,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_omp/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 21714866.09244757,\n            \"cpu_time\": 21467063.591836706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_omp/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122,\n            \"real_time\": 18675493.4838973,\n            \"cpu_time\": 18441887.631147593,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_omp/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114,\n            \"real_time\": 17438571.0351839,\n            \"cpu_time\": 17254878.938596476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_omp/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109,\n            \"real_time\": 17913056.248072706,\n            \"cpu_time\": 17311327.853210885,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_omp/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 18064284.79962051,\n            \"cpu_time\": 17676580.530000053,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_omp/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 14478039.413890136,\n            \"cpu_time\": 14209072.435714327,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_omp/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 247,\n            \"real_time\": 11060544.579037229,\n            \"cpu_time\": 10871543.51417001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_omp/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 253,\n            \"real_time\": 8013386.695310768,\n            \"cpu_time\": 7944493.501976294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_omp/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 372,\n            \"real_time\": 6325738.405951509,\n            \"cpu_time\": 6195711.026881711,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_omp/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 441,\n            \"real_time\": 5001837.920657277,\n            \"cpu_time\": 4938730.768707489,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_omp/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 520,\n            \"real_time\": 3769977.1153991325,\n            \"cpu_time\": 3701465.2788461545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_omp/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 608,\n            \"real_time\": 3296111.5179396556,\n            \"cpu_time\": 3250713.9588815807,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_omp/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 639,\n            \"real_time\": 2911125.159463867,\n            \"cpu_time\": 2845989.08607197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_omp/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 668,\n            \"real_time\": 2978487.211087172,\n            \"cpu_time\": 2924488.0838323208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_omp/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 234,\n            \"real_time\": 8407626.247817539,\n            \"cpu_time\": 7778359.858974317,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81948,\n            \"real_time\": 24540.274503863173,\n            \"cpu_time\": 24295.310501781507,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90450,\n            \"real_time\": 22354.358596126964,\n            \"cpu_time\": 22114.75158651178,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106862,\n            \"real_time\": 19562.374220622096,\n            \"cpu_time\": 19385.273090528088,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115534,\n            \"real_time\": 18559.42437674245,\n            \"cpu_time\": 18416.335615489847,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79968,\n            \"real_time\": 22904.185512123266,\n            \"cpu_time\": 22686.821303521465,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87487,\n            \"real_time\": 25243.202453151276,\n            \"cpu_time\": 25044.872872541106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83321,\n            \"real_time\": 24579.77229056028,\n            \"cpu_time\": 24406.666098582606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 89200,\n            \"real_time\": 23452.26192820792,\n            \"cpu_time\": 23243.68702914794,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 95901,\n            \"real_time\": 21603.611224089917,\n            \"cpu_time\": 21396.45751347742,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 103528,\n            \"real_time\": 19768.60924613651,\n            \"cpu_time\": 19611.185756510502,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113565,\n            \"real_time\": 18541.838145521946,\n            \"cpu_time\": 18362.74443710652,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117884,\n            \"real_time\": 17531.90774049164,\n            \"cpu_time\": 17338.754538359866,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114006,\n            \"real_time\": 18040.79448454231,\n            \"cpu_time\": 17830.28778309923,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111558,\n            \"real_time\": 19161.111234444616,\n            \"cpu_time\": 18945.944764158445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97916,\n            \"real_time\": 20270.132624257603,\n            \"cpu_time\": 20182.857234772833,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8303,\n            \"real_time\": 253236.9001590969,\n            \"cpu_time\": 250459.24786221856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10441,\n            \"real_time\": 197961.7395780509,\n            \"cpu_time\": 196162.56900680214,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12187,\n            \"real_time\": 161119.6313296689,\n            \"cpu_time\": 159654.94001805384,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14662,\n            \"real_time\": 141510.67542643435,\n            \"cpu_time\": 140369.95041604195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18433,\n            \"real_time\": 116589.32333639829,\n            \"cpu_time\": 115843.97596701577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20434,\n            \"real_time\": 101413.52143324054,\n            \"cpu_time\": 100520.98478026858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25053,\n            \"real_time\": 83226.05312479338,\n            \"cpu_time\": 82647.51718357086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27455,\n            \"real_time\": 76789.65544027885,\n            \"cpu_time\": 76438.58207976737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31396,\n            \"real_time\": 67870.22136416154,\n            \"cpu_time\": 67439.25436361249,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33944,\n            \"real_time\": 63140.80217511872,\n            \"cpu_time\": 62723.53052085743,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37350,\n            \"real_time\": 56813.61349479082,\n            \"cpu_time\": 56337.802168674934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38876,\n            \"real_time\": 53719.74151370136,\n            \"cpu_time\": 53163.97124189708,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39277,\n            \"real_time\": 52710.297401243944,\n            \"cpu_time\": 51979.08190544038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40369,\n            \"real_time\": 54255.577049793785,\n            \"cpu_time\": 53548.7684609477,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27168,\n            \"real_time\": 64402.872752429794,\n            \"cpu_time\": 64087.788906066045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 21923932.193407826,\n            \"cpu_time\": 21673013.1224491,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 18580971.660558134,\n            \"cpu_time\": 18394460.590000108,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 16370165.366419123,\n            \"cpu_time\": 16193614.161490746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 174,\n            \"real_time\": 9905376.84491097,\n            \"cpu_time\": 9853346.511494271,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 10035532.352048904,\n            \"cpu_time\": 9948177.196969664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 255,\n            \"real_time\": 7996179.568398671,\n            \"cpu_time\": 7933957.666666718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 346,\n            \"real_time\": 6385689.838170316,\n            \"cpu_time\": 6337395.739884405,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 311,\n            \"real_time\": 6566035.839387626,\n            \"cpu_time\": 6522831.852090006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 308,\n            \"real_time\": 5841974.912108491,\n            \"cpu_time\": 5796885.217532472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 390,\n            \"real_time\": 5866863.586915992,\n            \"cpu_time\": 5829508.900000036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 6575457.51457413,\n            \"cpu_time\": 6523123.37333342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 339,\n            \"real_time\": 5912406.162281897,\n            \"cpu_time\": 5833345.38643071,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 378,\n            \"real_time\": 4983235.089904161,\n            \"cpu_time\": 4891713.037037129,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 317,\n            \"real_time\": 6060687.081788428,\n            \"cpu_time\": 5971527.933753875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 291,\n            \"real_time\": 8473697.67013374,\n            \"cpu_time\": 8281456.261168409,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 1012502.0308070816,\n            \"cpu_time\": 69997.20829999773,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_taskflow/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12474,\n            \"real_time\": 2433231.9090104173,\n            \"cpu_time\": 184868.18278017934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_taskflow/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9068,\n            \"real_time\": 1499217.7407440073,\n            \"cpu_time\": 120061.18824437966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_taskflow/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5627,\n            \"real_time\": 1119299.945966871,\n            \"cpu_time\": 95987.23636041254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_taskflow/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4840,\n            \"real_time\": 1743259.860735679,\n            \"cpu_time\": 188158.54958677955,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_taskflow/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4393,\n            \"real_time\": 1997683.1636576657,\n            \"cpu_time\": 216161.2110175348,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_taskflow/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3723,\n            \"real_time\": 1858385.4431876317,\n            \"cpu_time\": 179211.18076818952,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_taskflow/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3408,\n            \"real_time\": 1910188.8538672186,\n            \"cpu_time\": 179181.720363849,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_taskflow/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2990,\n            \"real_time\": 1917513.1979669419,\n            \"cpu_time\": 171437.1963210725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_taskflow/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2618,\n            \"real_time\": 1860444.2379753995,\n            \"cpu_time\": 158018.29793736365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_taskflow/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2288,\n            \"real_time\": 1855939.16174477,\n            \"cpu_time\": 154893.89729021006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_taskflow/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1970,\n            \"real_time\": 1852478.6908898107,\n            \"cpu_time\": 138816.6862944282,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/96/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_taskflow/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1542,\n            \"real_time\": 1842383.985786944,\n            \"cpu_time\": 79035.6776913136,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/128/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_taskflow/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1640110.6900302693,\n            \"cpu_time\": 54394.21299996638,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/192/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_taskflow/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 2155663.8299953192,\n            \"cpu_time\": 53941.78799997462,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_taskflow/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 277,\n            \"real_time\": 21314442.99618784,\n            \"cpu_time\": 20923.6137184415,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_taskflow/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 434,\n            \"real_time\": 23181538.255820867,\n            \"cpu_time\": 15932.50921659016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_taskflow/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 494,\n            \"real_time\": 21663585.795572232,\n            \"cpu_time\": 35611.15182181216,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_taskflow/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418,\n            \"real_time\": 14317329.590872785,\n            \"cpu_time\": 29854.488038276006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_taskflow/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 507,\n            \"real_time\": 10737052.410280725,\n            \"cpu_time\": 14123.595660820589,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_taskflow/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 561,\n            \"real_time\": 12690871.465061385,\n            \"cpu_time\": 39777.80213896646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_taskflow/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 730,\n            \"real_time\": 17279020.178112622,\n            \"cpu_time\": 42826.7643835874,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_taskflow/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 851,\n            \"real_time\": 18369660.877757274,\n            \"cpu_time\": 47711.72032903988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_taskflow/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 997,\n            \"real_time\": 19351821.975902084,\n            \"cpu_time\": 56237.045135437285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_taskflow/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 978,\n            \"real_time\": 17373276.05939674,\n            \"cpu_time\": 58721.058282205966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_taskflow/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1089,\n            \"real_time\": 17069242.209306415,\n            \"cpu_time\": 58839.678604209555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_taskflow/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1088,\n            \"real_time\": 15856202.943027977,\n            \"cpu_time\": 64910.26470592356,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/96/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_taskflow/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1085,\n            \"real_time\": 15108879.653453689,\n            \"cpu_time\": 50229.264516155825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/128/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_taskflow/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1019,\n            \"real_time\": 14598880.534839906,\n            \"cpu_time\": 49834.601570173334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/192/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_taskflow/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 953,\n            \"real_time\": 14576062.559348542,\n            \"cpu_time\": 87874.264428125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_taskflow/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 200012609.49842012,\n            \"cpu_time\": 16700.500001181557,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_taskflow/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 258498884.56539938,\n            \"cpu_time\": 15442.434781344555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_taskflow/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 185123988.1652873,\n            \"cpu_time\": 16984.708333704173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_taskflow/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 213046969.000802,\n            \"cpu_time\": 17474.518518543777,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_taskflow/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 221819641.17626196,\n            \"cpu_time\": 17825.674999016883,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_taskflow/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 264321961.3553009,\n            \"cpu_time\": 24499.847458080974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_taskflow/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 247957636.84740064,\n            \"cpu_time\": 22563.40909129352,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_taskflow/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 258675649.36979085,\n            \"cpu_time\": 24964.407407002942,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_taskflow/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 203259672.52481344,\n            \"cpu_time\": 23049.29487177805,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_taskflow/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 201954033.2270977,\n            \"cpu_time\": 23720.431818348556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_taskflow/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92,\n            \"real_time\": 187184466.54384023,\n            \"cpu_time\": 22927.934782911587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_taskflow/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 202122975.23837712,\n            \"cpu_time\": 27470.619047454376,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/96/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_taskflow/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 204517530.77806032,\n            \"cpu_time\": 23912.68141605198,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/128/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_taskflow/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 205455565.29247886,\n            \"cpu_time\": 26067.0707966992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/192/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_taskflow/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117,\n            \"real_time\": 214881837.64959726,\n            \"cpu_time\": 48448.538461603974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13723098,\n            \"real_time\": 149.61118094670408,\n            \"cpu_time\": 148.2072505785538,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13973739,\n            \"real_time\": 149.38001612164715,\n            \"cpu_time\": 147.876298104608,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13787576,\n            \"real_time\": 150.43078616512554,\n            \"cpu_time\": 148.90648124079198,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13429813,\n            \"real_time\": 151.0383588350627,\n            \"cpu_time\": 149.6210866078347,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13219501,\n            \"real_time\": 150.83205236033433,\n            \"cpu_time\": 149.34720380141357,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13972538,\n            \"real_time\": 148.25166694870714,\n            \"cpu_time\": 146.8615826272932,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13820155,\n            \"real_time\": 150.48665518043407,\n            \"cpu_time\": 148.988025459914,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13976443,\n            \"real_time\": 153.07804303421852,\n            \"cpu_time\": 151.53571763573686,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13716379,\n            \"real_time\": 151.92769032502483,\n            \"cpu_time\": 150.36377443347124,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12982246,\n            \"real_time\": 148.35583111169882,\n            \"cpu_time\": 146.8705545250035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13821339,\n            \"real_time\": 151.38875431015967,\n            \"cpu_time\": 149.88921927173743,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14139547,\n            \"real_time\": 154.5471518311366,\n            \"cpu_time\": 152.89377990681007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13128243,\n            \"real_time\": 150.09538709677673,\n            \"cpu_time\": 148.60651733822738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13586629,\n            \"real_time\": 150.75179215093763,\n            \"cpu_time\": 149.25392751947533,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12850018,\n            \"real_time\": 153.91277685815493,\n            \"cpu_time\": 152.40551320628384,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14986,\n            \"real_time\": 144541.080940483,\n            \"cpu_time\": 143057.18770853078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22365,\n            \"real_time\": 96730.55577956568,\n            \"cpu_time\": 95742.24457858341,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31028,\n            \"real_time\": 67619.90766465041,\n            \"cpu_time\": 66972.40189506266,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40034,\n            \"real_time\": 52457.446046075864,\n            \"cpu_time\": 52000.627017034254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51993,\n            \"real_time\": 37147.996018067875,\n            \"cpu_time\": 36824.94545419578,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 63539,\n            \"real_time\": 31959.86605036914,\n            \"cpu_time\": 31652.359527220182,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55435,\n            \"real_time\": 38171.69459803292,\n            \"cpu_time\": 37900.734373591426,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52510,\n            \"real_time\": 41170.93334540972,\n            \"cpu_time\": 40821.603884973534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47623,\n            \"real_time\": 44117.384477506435,\n            \"cpu_time\": 43859.35193078989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48962,\n            \"real_time\": 43176.80709504921,\n            \"cpu_time\": 42910.0752215998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53221,\n            \"real_time\": 42286.29317292531,\n            \"cpu_time\": 42116.364912346675,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55248,\n            \"real_time\": 35061.372302416894,\n            \"cpu_time\": 34904.54447219822,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56162,\n            \"real_time\": 35672.71995283248,\n            \"cpu_time\": 35124.772087889476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53001,\n            \"real_time\": 38213.318484197625,\n            \"cpu_time\": 37381.72347691546,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42370,\n            \"real_time\": 53955.16301712985,\n            \"cpu_time\": 41246.84649516102,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102,\n            \"real_time\": 20892851.117441393,\n            \"cpu_time\": 20728916.068627674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 145,\n            \"real_time\": 17081643.027606707,\n            \"cpu_time\": 16905753.703448337,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125,\n            \"real_time\": 13725195.16851753,\n            \"cpu_time\": 13579886.33599962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 12465606.128367094,\n            \"cpu_time\": 12326138.312820287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 201,\n            \"real_time\": 8303066.8511263905,\n            \"cpu_time\": 8215738.58706474,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 280,\n            \"real_time\": 9663655.05716697,\n            \"cpu_time\": 9550102.046428729,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 246,\n            \"real_time\": 6277820.284239857,\n            \"cpu_time\": 6226132.808942945,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 296,\n            \"real_time\": 6293089.594298697,\n            \"cpu_time\": 6233331.62162158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 384,\n            \"real_time\": 5955852.953168991,\n            \"cpu_time\": 5885434.828124906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 387,\n            \"real_time\": 5780447.599326455,\n            \"cpu_time\": 5724110.816537395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 384,\n            \"real_time\": 5358049.182177638,\n            \"cpu_time\": 5303609.434895939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 398,\n            \"real_time\": 5901207.768618031,\n            \"cpu_time\": 5834053.339196055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 375,\n            \"real_time\": 5717746.178619564,\n            \"cpu_time\": 5576748.11199998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 362,\n            \"real_time\": 5848543.381431649,\n            \"cpu_time\": 5244469.093922697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 372,\n            \"real_time\": 5903559.317249023,\n            \"cpu_time\": 3323073.2688172148,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13187326,\n            \"real_time\": 148.7569423132739,\n            \"cpu_time\": 147.4117439729593,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13534604,\n            \"real_time\": 150.12663148199582,\n            \"cpu_time\": 148.59519879561864,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000000,\n            \"real_time\": 151.33309459779412,\n            \"cpu_time\": 149.8622087000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13720530,\n            \"real_time\": 149.95293184418998,\n            \"cpu_time\": 148.39297767651627,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13852520,\n            \"real_time\": 148.55272296669986,\n            \"cpu_time\": 147.0373039706845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13675605,\n            \"real_time\": 148.70390560840826,\n            \"cpu_time\": 147.28778902286234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14154836,\n            \"real_time\": 149.00057901833745,\n            \"cpu_time\": 147.54957627202208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static_chunk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14368768,\n            \"real_time\": 148.37784797964196,\n            \"cpu_time\": 146.90424774065607,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static_chunk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13721226,\n            \"real_time\": 150.86870576082663,\n            \"cpu_time\": 149.35289936919744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static_chunk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13700558,\n            \"real_time\": 148.21767179469447,\n            \"cpu_time\": 146.73125036220904,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static_chunk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14249542,\n            \"real_time\": 145.97334911178078,\n            \"cpu_time\": 144.50226645880977,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static_chunk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13776198,\n            \"real_time\": 149.01287096526926,\n            \"cpu_time\": 147.46998097733635,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/96/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static_chunk/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13514864,\n            \"real_time\": 152.0472191970403,\n            \"cpu_time\": 150.50577971039962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/128/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static_chunk/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13254425,\n            \"real_time\": 152.83689009531287,\n            \"cpu_time\": 151.32372411477832,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/192/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static_chunk/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13252874,\n            \"real_time\": 156.82449792420257,\n            \"cpu_time\": 155.1388581073042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14575,\n            \"real_time\": 144231.91052978125,\n            \"cpu_time\": 142606.0358147525,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22079,\n            \"real_time\": 93135.08655053891,\n            \"cpu_time\": 92163.43525522077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30409,\n            \"real_time\": 68440.67299228472,\n            \"cpu_time\": 67826.34858101197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39913,\n            \"real_time\": 52987.21366522632,\n            \"cpu_time\": 52588.31558640023,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47550,\n            \"real_time\": 41571.335204055315,\n            \"cpu_time\": 41328.28744479591,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53844,\n            \"real_time\": 36211.87046066524,\n            \"cpu_time\": 35936.461332739476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51964,\n            \"real_time\": 37606.773575867235,\n            \"cpu_time\": 37302.6051304747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static_chunk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57664,\n            \"real_time\": 41106.08431430196,\n            \"cpu_time\": 40870.41089761373,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static_chunk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50984,\n            \"real_time\": 43552.34995246662,\n            \"cpu_time\": 43329.93266514958,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static_chunk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55061,\n            \"real_time\": 43395.934635678415,\n            \"cpu_time\": 43185.64348631566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static_chunk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51202,\n            \"real_time\": 40943.646596378036,\n            \"cpu_time\": 40745.71860474172,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static_chunk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57089,\n            \"real_time\": 35730.4011459677,\n            \"cpu_time\": 35297.01854998343,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/96/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static_chunk/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57094,\n            \"real_time\": 36416.45680934485,\n            \"cpu_time\": 35912.69594002925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/128/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static_chunk/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52578,\n            \"real_time\": 38262.451996940996,\n            \"cpu_time\": 37771.40965803224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/192/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static_chunk/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39451,\n            \"real_time\": 58476.61417713335,\n            \"cpu_time\": 44005.86829231142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 22681746.15313242,\n            \"cpu_time\": 22434021.520408534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 18026406.000135466,\n            \"cpu_time\": 17824503.23999967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 133,\n            \"real_time\": 16736477.39899982,\n            \"cpu_time\": 16524899.060150398,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131,\n            \"real_time\": 14605264.252279209,\n            \"cpu_time\": 14434406.740457939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 214,\n            \"real_time\": 10118236.911056617,\n            \"cpu_time\": 10015481.05607441,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 242,\n            \"real_time\": 8231141.27688464,\n            \"cpu_time\": 8148199.632231365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 261,\n            \"real_time\": 7737237.33698828,\n            \"cpu_time\": 7666410.586206947,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_static_chunk/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 348,\n            \"real_time\": 6204031.629289833,\n            \"cpu_time\": 6140013.307471244,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_static_chunk/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 369,\n            \"real_time\": 5705067.726372058,\n            \"cpu_time\": 5637635.490514858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_static_chunk/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 391,\n            \"real_time\": 5263303.248140285,\n            \"cpu_time\": 5217155.910486035,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_static_chunk/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 384,\n            \"real_time\": 5333656.9114132235,\n            \"cpu_time\": 5276667.510416703,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_static_chunk/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 395,\n            \"real_time\": 5445617.820206983,\n            \"cpu_time\": 5370566.498734235,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/96/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_static_chunk/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 393,\n            \"real_time\": 5661304.707463556,\n            \"cpu_time\": 5522905.127226464,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/128/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_static_chunk/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 380,\n            \"real_time\": 6031501.081490301,\n            \"cpu_time\": 5118290.250000033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/192/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_static_chunk/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 376,\n            \"real_time\": 6002672.84577019,\n            \"cpu_time\": 3621195.9202128635,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13974819,\n            \"real_time\": 149.4653872799041,\n            \"cpu_time\": 148.01514023187192,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13879194,\n            \"real_time\": 149.5856694566477,\n            \"cpu_time\": 147.9030734061375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13919298,\n            \"real_time\": 149.10413484640995,\n            \"cpu_time\": 147.65429283861513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13986496,\n            \"real_time\": 149.77357788418072,\n            \"cpu_time\": 148.32170030291883,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14060843,\n            \"real_time\": 150.44423595306677,\n            \"cpu_time\": 149.02234844666933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14139367,\n            \"real_time\": 148.27148379272955,\n            \"cpu_time\": 146.88532513513275,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13515390,\n            \"real_time\": 148.79993148358662,\n            \"cpu_time\": 147.37372565646083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14365550,\n            \"real_time\": 149.9531685880817,\n            \"cpu_time\": 148.55423551482548,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000000,\n            \"real_time\": 150.94097079709172,\n            \"cpu_time\": 149.5571449999943,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13828694,\n            \"real_time\": 153.85405924446587,\n            \"cpu_time\": 152.36746174295615,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13372587,\n            \"real_time\": 153.28329881149796,\n            \"cpu_time\": 151.8413972554446,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13504076,\n            \"real_time\": 150.55381745045105,\n            \"cpu_time\": 149.03893965051586,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/96/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto_chunk/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13395755,\n            \"real_time\": 152.7694527074495,\n            \"cpu_time\": 151.33302549949698,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/128/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto_chunk/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13283786,\n            \"real_time\": 157.73919280602166,\n            \"cpu_time\": 156.07321978839445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/192/1000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto_chunk/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13228584,\n            \"real_time\": 155.03225522833677,\n            \"cpu_time\": 153.53118565071125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14975,\n            \"real_time\": 138642.68681721666,\n            \"cpu_time\": 137239.8552921565,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25536,\n            \"real_time\": 80908.42347974332,\n            \"cpu_time\": 80136.95089285492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32652,\n            \"real_time\": 58912.96061649863,\n            \"cpu_time\": 58282.10097390526,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38814,\n            \"real_time\": 56165.083218255524,\n            \"cpu_time\": 55693.031097026585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48798,\n            \"real_time\": 35555.08270985147,\n            \"cpu_time\": 35159.23888274015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48977,\n            \"real_time\": 33297.21022076906,\n            \"cpu_time\": 32983.653020804566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42450,\n            \"real_time\": 46669.43154358102,\n            \"cpu_time\": 46469.04864546407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52998,\n            \"real_time\": 46507.96607376841,\n            \"cpu_time\": 46281.993245027654,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61572,\n            \"real_time\": 42744.63520740719,\n            \"cpu_time\": 42560.28538946366,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48042,\n            \"real_time\": 41167.97487735984,\n            \"cpu_time\": 40994.7981974109,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51707,\n            \"real_time\": 38917.948537296455,\n            \"cpu_time\": 38541.94869166567,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48369,\n            \"real_time\": 39425.76790908441,\n            \"cpu_time\": 39102.91356033744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/96/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_auto_chunk/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53809,\n            \"real_time\": 38871.64232767334,\n            \"cpu_time\": 38241.37854262402,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/128/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_auto_chunk/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54234,\n            \"real_time\": 37002.5952551935,\n            \"cpu_time\": 36347.888888888476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/192/1000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_auto_chunk/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43531,\n            \"real_time\": 54609.48999553103,\n            \"cpu_time\": 41887.624520458485,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 20851639.248107992,\n            \"cpu_time\": 20595477.56435578,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125,\n            \"real_time\": 18524814.27974999,\n            \"cpu_time\": 18305795.927999496,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 18001617.749687284,\n            \"cpu_time\": 17808552.40000051,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 227,\n            \"real_time\": 13640183.630288633,\n            \"cpu_time\": 13480201.339207008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 9064748.710370623,\n            \"cpu_time\": 8990963.60499982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 248,\n            \"real_time\": 7840320.475928996,\n            \"cpu_time\": 7792757.637097045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 340,\n            \"real_time\": 6212999.1854924485,\n            \"cpu_time\": 6163495.305882554,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 350,\n            \"real_time\": 5800308.714221631,\n            \"cpu_time\": 5760558.408571471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 332,\n            \"real_time\": 5553317.50908945,\n            \"cpu_time\": 5513182.454819456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321,\n            \"real_time\": 6572704.218223551,\n            \"cpu_time\": 6504563.342679131,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 309,\n            \"real_time\": 7117333.378519223,\n            \"cpu_time\": 7002175.977346317,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 300,\n            \"real_time\": 7145794.129852827,\n            \"cpu_time\": 7078960.196666533,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/96/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_auto_chunk/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 318,\n            \"real_time\": 6937983.78957787,\n            \"cpu_time\": 6734189.45911954,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/128/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_auto_chunk/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 319,\n            \"real_time\": 6718327.893093111,\n            \"cpu_time\": 5373253.87460825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/192/100000000/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_auto_chunk/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 280,\n            \"real_time\": 7957426.92841616,\n            \"cpu_time\": 3883602.7500000875,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:00:46-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/simple_pool_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            42.4438,\n            35.9297,\n            34.1357\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84013,\n            \"real_time\": 24.927065692179184,\n            \"cpu_time\": 24.68703292347613,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78702,\n            \"real_time\": 26.329147187883446,\n            \"cpu_time\": 26.03303855048156,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78608,\n            \"real_time\": 26.45929264204295,\n            \"cpu_time\": 26.184991680236102,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76981,\n            \"real_time\": 27.446563866006528,\n            \"cpu_time\": 27.157246463413042,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72467,\n            \"real_time\": 28.70057424631941,\n            \"cpu_time\": 28.371959554003887,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64240,\n            \"real_time\": 36.240268633413855,\n            \"cpu_time\": 35.94460526151931,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27839,\n            \"real_time\": 72.30507148525898,\n            \"cpu_time\": 71.75490538453248,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39863,\n            \"real_time\": 51.466464692080464,\n            \"cpu_time\": 51.046581541780654,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15345,\n            \"real_time\": 175.06843337193786,\n            \"cpu_time\": 173.38521700879767,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13874,\n            \"real_time\": 152.23555614609532,\n            \"cpu_time\": 150.52818869828462,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5256,\n            \"real_time\": 377.8091076774951,\n            \"cpu_time\": 373.3370525114153,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3287,\n            \"real_time\": 636.4516592730467,\n            \"cpu_time\": 629.2268947368427,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2551,\n            \"real_time\": 857.7263606193807,\n            \"cpu_time\": 846.5683018424148,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1467,\n            \"real_time\": 1437.8365998815975,\n            \"cpu_time\": 1418.4732897068832,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1827,\n            \"real_time\": 1145.5587564585767,\n            \"cpu_time\": 1140.7272627257794,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8102,\n            \"real_time\": 263.31877018242494,\n            \"cpu_time\": 261.20214465564055,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7976,\n            \"real_time\": 274.82677019028876,\n            \"cpu_time\": 272.17537700601804,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7203,\n            \"real_time\": 287.0116065640696,\n            \"cpu_time\": 284.40989893100044,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7251,\n            \"real_time\": 285.86862528836144,\n            \"cpu_time\": 282.66381768032045,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7104,\n            \"real_time\": 306.7960046341345,\n            \"cpu_time\": 303.4912108671171,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5644,\n            \"real_time\": 373.3840963834914,\n            \"cpu_time\": 369.59469613749184,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4095,\n            \"real_time\": 515.0495367681879,\n            \"cpu_time\": 510.52256971916876,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2972,\n            \"real_time\": 671.9443664342681,\n            \"cpu_time\": 664.737473755048,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1834.2539200093597,\n            \"cpu_time\": 1813.8713190000003,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 631,\n            \"real_time\": 3276.850437456166,\n            \"cpu_time\": 3243.52492234549,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 453,\n            \"real_time\": 4719.372044130338,\n            \"cpu_time\": 4669.445516556302,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 381,\n            \"real_time\": 5592.753475145718,\n            \"cpu_time\": 5524.159212598414,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 305,\n            \"real_time\": 7139.984721348423,\n            \"cpu_time\": 7060.785357377062,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 246,\n            \"real_time\": 8655.248829296117,\n            \"cpu_time\": 8562.705211382137,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 184,\n            \"real_time\": 11522.855125013333,\n            \"cpu_time\": 11481.054211956514,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61,\n            \"real_time\": 33897.193129647705,\n            \"cpu_time\": 33556.53211475397,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 34631.4642377103,\n            \"cpu_time\": 34262.31715254228,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 35223.01955993082,\n            \"cpu_time\": 34820.329983050666,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57,\n            \"real_time\": 37308.14375408125,\n            \"cpu_time\": 36944.56496491228,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 40078.42890806151,\n            \"cpu_time\": 39683.88427777772,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 42137.80499897742,\n            \"cpu_time\": 41697.38910416676,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 63213.63420883084,\n            \"cpu_time\": 62941.80555882387,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26,\n            \"real_time\": 80289.49611784461,\n            \"cpu_time\": 79525.3845384614,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 168674.38628936984,\n            \"cpu_time\": 166778.7295714283,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 314954.0234257334,\n            \"cpu_time\": 312179.69228571415,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 477441.73000101,\n            \"cpu_time\": 472167.5269999991,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 582578.1119929161,\n            \"cpu_time\": 575699.746999998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 808698.0386869982,\n            \"cpu_time\": 798228.6050000009,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 927672.6834941655,\n            \"cpu_time\": 917007.7765000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1129510.3834709153,\n            \"cpu_time\": 1098350.1615000009,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6862,\n            \"real_time\": 269.13754211025355,\n            \"cpu_time\": 242.60559676479167,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6608,\n            \"real_time\": 278.93653556157113,\n            \"cpu_time\": 274.9374842615007,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6356,\n            \"real_time\": 354.4661606418155,\n            \"cpu_time\": 348.44239789175606,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4548,\n            \"real_time\": 427.1909511806206,\n            \"cpu_time\": 420.78250615655105,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4826,\n            \"real_time\": 511.76684523187345,\n            \"cpu_time\": 504.41389017819955,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5395,\n            \"real_time\": 486.5229397578868,\n            \"cpu_time\": 478.1304680259506,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5710,\n            \"real_time\": 452.887560073743,\n            \"cpu_time\": 447.2017222416828,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3182,\n            \"real_time\": 518.2549154730121,\n            \"cpu_time\": 510.57097140163535,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3456,\n            \"real_time\": 618.1528434791727,\n            \"cpu_time\": 609.6165300925912,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3684,\n            \"real_time\": 448.00666232677287,\n            \"cpu_time\": 442.2984964712253,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4302,\n            \"real_time\": 446.5722677606166,\n            \"cpu_time\": 440.2936327289573,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3281,\n            \"real_time\": 478.3706501179086,\n            \"cpu_time\": 470.8061176470632,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4821,\n            \"real_time\": 490.44937359003376,\n            \"cpu_time\": 482.8383335407632,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3046,\n            \"real_time\": 532.9109185854693,\n            \"cpu_time\": 524.4726162179899,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3775,\n            \"real_time\": 700.3198381488686,\n            \"cpu_time\": 690.3106855629134,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1017,\n            \"real_time\": 2010.886523173893,\n            \"cpu_time\": 1745.1510707964492,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 628,\n            \"real_time\": 3757.041840811088,\n            \"cpu_time\": 3714.192695859844,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 654,\n            \"real_time\": 4844.02545258568,\n            \"cpu_time\": 4810.957799694181,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 484,\n            \"real_time\": 3914.6886010411818,\n            \"cpu_time\": 3880.1076301652533,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 508,\n            \"real_time\": 4235.994653532458,\n            \"cpu_time\": 4201.828350393712,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_folly/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 465,\n            \"real_time\": 4649.032283854741,\n            \"cpu_time\": 4613.1239204300755,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_folly/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 419,\n            \"real_time\": 4609.0470812547965,\n            \"cpu_time\": 4571.941145584732,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_folly/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 301,\n            \"real_time\": 6889.265382189019,\n            \"cpu_time\": 6825.806501661133,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_folly/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 384,\n            \"real_time\": 5035.754096146168,\n            \"cpu_time\": 4991.876632812457,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_folly/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 363,\n            \"real_time\": 5895.224203914917,\n            \"cpu_time\": 5850.758024793446,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_folly/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 293,\n            \"real_time\": 6285.655474347466,\n            \"cpu_time\": 6240.814061433452,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_folly/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 280,\n            \"real_time\": 6649.934910819866,\n            \"cpu_time\": 6601.096414285682,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_folly/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 281,\n            \"real_time\": 5771.14592886321,\n            \"cpu_time\": 5717.410234875498,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_folly/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 307,\n            \"real_time\": 5785.03550829651,\n            \"cpu_time\": 5731.392338762225,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_folly/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 318,\n            \"real_time\": 7144.154317431011,\n            \"cpu_time\": 7059.912204402552,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_folly/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 215967.3314438098,\n            \"cpu_time\": 174171.0745555546,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_folly/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 276269.13983840495,\n            \"cpu_time\": 273526.7415000019,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_folly/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 395009.3394960277,\n            \"cpu_time\": 392011.6352500003,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_folly/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 405391.7092678603,\n            \"cpu_time\": 402856.2744999959,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_folly/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 446125.33778417856,\n            \"cpu_time\": 442730.3953999967,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_folly/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 477376.88475172035,\n            \"cpu_time\": 473848.45000000554,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_folly/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 476656.07373346575,\n            \"cpu_time\": 473220.5612500025,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/16/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_folly/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 560906.1277646106,\n            \"cpu_time\": 556630.1859999996,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/24/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_folly/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 617663.1397393066,\n            \"cpu_time\": 613979.6017500032,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/32/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_folly/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 570848.9939958478,\n            \"cpu_time\": 567711.1103333345,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/48/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_folly/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 505241.53766067076,\n            \"cpu_time\": 501337.2786666726,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/64/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_folly/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 662707.637733547,\n            \"cpu_time\": 657784.7492499984,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/96/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_folly/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 630678.9189887544,\n            \"cpu_time\": 624332.7216666709,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/128/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_folly/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 649783.1986829018,\n            \"cpu_time\": 642848.0319999986,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/192/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_folly/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 694757.3783497015,\n            \"cpu_time\": 686438.1263333333,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 116285,\n            \"real_time\": 16.521736001990295,\n            \"cpu_time\": 16.333456868899752,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 517092,\n            \"real_time\": 3.437250282336804,\n            \"cpu_time\": 3.4043385374362827,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 163767,\n            \"real_time\": 82.48202245936636,\n            \"cpu_time\": 81.85555459280552,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8352,\n            \"real_time\": 238.60889164150169,\n            \"cpu_time\": 236.5851628352539,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8272,\n            \"real_time\": 285.6565791735474,\n            \"cpu_time\": 284.22409453578615,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6632,\n            \"real_time\": 268.86470386473655,\n            \"cpu_time\": 267.6266709891417,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5600,\n            \"real_time\": 552.7195157316912,\n            \"cpu_time\": 550.6370285714318,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10616,\n            \"real_time\": 561.1728238562625,\n            \"cpu_time\": 558.6144278447654,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9145,\n            \"real_time\": 221.64628649524582,\n            \"cpu_time\": 219.9493708037164,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5201,\n            \"real_time\": 423.68281675906275,\n            \"cpu_time\": 420.07535397039055,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5016,\n            \"real_time\": 299.9373104178571,\n            \"cpu_time\": 296.8051568979212,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4360,\n            \"real_time\": 399.2788882930379,\n            \"cpu_time\": 396.2079116972448,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5016,\n            \"real_time\": 497.9731720494199,\n            \"cpu_time\": 496.2065522328497,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4190,\n            \"real_time\": 398.63692219246866,\n            \"cpu_time\": 395.9109083532282,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5471,\n            \"real_time\": 383.21899944513603,\n            \"cpu_time\": 380.68299707547993,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15654,\n            \"real_time\": 132.30819975826626,\n            \"cpu_time\": 130.9847571866634,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74348,\n            \"real_time\": 28.237171047271204,\n            \"cpu_time\": 27.932300989939215,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8197,\n            \"real_time\": 486.3578481246338,\n            \"cpu_time\": 481.26742320360756,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1322,\n            \"real_time\": 2529.4653509684335,\n            \"cpu_time\": 2516.841250378236,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 721,\n            \"real_time\": 2136.004001390442,\n            \"cpu_time\": 2123.0637101248453,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 863,\n            \"real_time\": 2514.671435690812,\n            \"cpu_time\": 2500.6162155272423,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 730,\n            \"real_time\": 3018.0796752811398,\n            \"cpu_time\": 2995.6753616438023,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 788,\n            \"real_time\": 2930.253258963035,\n            \"cpu_time\": 2908.098394670022,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 553,\n            \"real_time\": 3561.7206038092054,\n            \"cpu_time\": 3537.7510741411106,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 639,\n            \"real_time\": 4842.360783987773,\n            \"cpu_time\": 4803.001397496173,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 475,\n            \"real_time\": 5285.769109614193,\n            \"cpu_time\": 5261.921172631638,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 471,\n            \"real_time\": 4803.573193163028,\n            \"cpu_time\": 4785.855991507336,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 526,\n            \"real_time\": 4896.998193872802,\n            \"cpu_time\": 4879.588262357398,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 443,\n            \"real_time\": 5149.824611798484,\n            \"cpu_time\": 5128.650020316006,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 602,\n            \"real_time\": 3664.4027757913223,\n            \"cpu_time\": 3636.106264119565,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 156,\n            \"real_time\": 13481.202903979769,\n            \"cpu_time\": 13365.92343589725,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 911,\n            \"real_time\": 2947.1443183198735,\n            \"cpu_time\": 2920.205652030728,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 56462.300982309025,\n            \"cpu_time\": 55907.24807407389,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 188927.95814567112,\n            \"cpu_time\": 187946.78100000185,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 214237.81900666654,\n            \"cpu_time\": 212957.10420000093,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 353281.404163378,\n            \"cpu_time\": 351599.99216667376,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 366008.5449926555,\n            \"cpu_time\": 364111.34799999447,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 279008.6681322594,\n            \"cpu_time\": 277205.8017142902,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 363004.38226317056,\n            \"cpu_time\": 361651.05924999353,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 438891.9136021286,\n            \"cpu_time\": 437396.06859999185,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 356638.30938283354,\n            \"cpu_time\": 355100.17419999256,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 365818.34838725626,\n            \"cpu_time\": 363298.519,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 384193.06848663837,\n            \"cpu_time\": 382546.4144999984,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 381785.8848293933,\n            \"cpu_time\": 379406.12749999523,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 354469.02667172253,\n            \"cpu_time\": 351889.6868333362,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2009485,\n            \"real_time\": 1.0502425700769027,\n            \"cpu_time\": 1.03952200140831,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418074,\n            \"real_time\": 4.99290260076885,\n            \"cpu_time\": 4.950165085606905,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73843,\n            \"real_time\": 27.21966166059483,\n            \"cpu_time\": 26.984977736549272,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46978,\n            \"real_time\": 43.97671725141422,\n            \"cpu_time\": 43.53079716037292,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36870,\n            \"real_time\": 59.30666154066613,\n            \"cpu_time\": 58.74844190398642,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19875,\n            \"real_time\": 102.16786168843696,\n            \"cpu_time\": 101.46306163521885,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 170.2692574937828,\n            \"cpu_time\": 169.04900870000006,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13499,\n            \"real_time\": 150.92567923334659,\n            \"cpu_time\": 150.12243188384397,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13124,\n            \"real_time\": 159.41165712003786,\n            \"cpu_time\": 158.6611434014046,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13036,\n            \"real_time\": 151.59976234750712,\n            \"cpu_time\": 150.5931126112294,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21034,\n            \"real_time\": 98.11694822662457,\n            \"cpu_time\": 97.63098635542607,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13365,\n            \"real_time\": 153.45995248742386,\n            \"cpu_time\": 152.4459536101777,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13914,\n            \"real_time\": 150.18007841386384,\n            \"cpu_time\": 148.16603032916737,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12954,\n            \"real_time\": 167.11171290584016,\n            \"cpu_time\": 162.9913093253059,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10839,\n            \"real_time\": 196.02369462225914,\n            \"cpu_time\": 164.45406162930126,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 205247,\n            \"real_time\": 10.109557947339345,\n            \"cpu_time\": 10.009145687878748,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56242,\n            \"real_time\": 44.73185133896239,\n            \"cpu_time\": 44.31086342946594,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8533,\n            \"real_time\": 291.9235122402643,\n            \"cpu_time\": 288.7029119887547,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4296,\n            \"real_time\": 471.6253898995781,\n            \"cpu_time\": 467.18349022346666,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3233,\n            \"real_time\": 615.5942675366334,\n            \"cpu_time\": 610.0820711413476,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2574,\n            \"real_time\": 937.1221643346474,\n            \"cpu_time\": 928.6206802641896,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1758.5095409303904,\n            \"cpu_time\": 1739.3213779999996,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1195,\n            \"real_time\": 1626.2682075865534,\n            \"cpu_time\": 1607.174887029272,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1233,\n            \"real_time\": 1552.580257092919,\n            \"cpu_time\": 1537.4342952149286,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1263,\n            \"real_time\": 1370.9539501107079,\n            \"cpu_time\": 1363.0314679334956,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1343,\n            \"real_time\": 1478.9639762377371,\n            \"cpu_time\": 1467.980083395388,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1271,\n            \"real_time\": 1550.3636120403087,\n            \"cpu_time\": 1536.5134870181048,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_bulk/96/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1278,\n            \"real_time\": 1556.784197132807,\n            \"cpu_time\": 1533.4214436619664,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_bulk/128/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1296,\n            \"real_time\": 1647.0284830530197,\n            \"cpu_time\": 1633.5809768518518,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_bulk/192/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1299,\n            \"real_time\": 1587.5697459450553,\n            \"cpu_time\": 1527.3406774442108,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2083,\n            \"real_time\": 987.4532030416054,\n            \"cpu_time\": 978.4291598655876,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 641,\n            \"real_time\": 3870.3117051413183,\n            \"cpu_time\": 3833.4771404056023,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 35303.08223773979,\n            \"cpu_time\": 34913.54740909067,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 48173.12866604576,\n            \"cpu_time\": 47674.33757575818,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 43775.44354938436,\n            \"cpu_time\": 43325.03779999968,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 161228.20807728343,\n            \"cpu_time\": 159779.31123076746,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 157661.44500006564,\n            \"cpu_time\": 156839.76561538552,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_bulk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 155586.16061193438,\n            \"cpu_time\": 154740.92853845778,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_bulk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 156651.09656817678,\n            \"cpu_time\": 155631.34778571452,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_bulk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 159689.32940158993,\n            \"cpu_time\": 158493.5649999977,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_bulk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 153666.270386356,\n            \"cpu_time\": 152443.85823077138,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_bulk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 158513.41172121465,\n            \"cpu_time\": 156606.41060000216,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/96/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_bulk/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 151935.3028968908,\n            \"cpu_time\": 150106.56599999947,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/128/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_bulk/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 154440.88949256443,\n            \"cpu_time\": 152582.70735714064,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/192/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_bulk/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 148155.81942509327,\n            \"cpu_time\": 147403.2743571375,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"small_buffer_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:09:29-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/small_buffer_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            53.8154,\n            30.5488,\n            30.9009\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26346,\n            \"real_time\": 78683.88066652126,\n            \"cpu_time\": 77930.26675776207,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6389,\n            \"real_time\": 330888.496627741,\n            \"cpu_time\": 327502.1726404758,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13282,\n            \"real_time\": 156759.58997214196,\n            \"cpu_time\": 155267.122496612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3419,\n            \"real_time\": 523717.6264852773,\n            \"cpu_time\": 518971.49107926304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4917,\n            \"real_time\": 430077.6971718124,\n            \"cpu_time\": 425532.4584095991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1040,\n            \"real_time\": 2048902.4556949376,\n            \"cpu_time\": 2027999.833653845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18877,\n            \"real_time\": 112376.09196133995,\n            \"cpu_time\": 111355.80203422143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4713,\n            \"real_time\": 450040.82409814774,\n            \"cpu_time\": 445699.9023976236,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2740,\n            \"real_time\": 782766.3094818211,\n            \"cpu_time\": 774622.812043795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 607,\n            \"real_time\": 3539301.873118765,\n            \"cpu_time\": 3499584.1317957127,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18727,\n            \"real_time\": 112184.39382140143,\n            \"cpu_time\": 111102.67880600218,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4499,\n            \"real_time\": 452319.70194350433,\n            \"cpu_time\": 448116.87019337586,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 21120,\n            \"real_time\": 98552.20900080343,\n            \"cpu_time\": 97971.89318181817,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 5264,\n            \"real_time\": 389286.9101982354,\n            \"cpu_time\": 387312.53438449925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 10416,\n            \"real_time\": 195985.78937062365,\n            \"cpu_time\": 195176.5913978492,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2688,\n            \"real_time\": 791073.308781571,\n            \"cpu_time\": 787507.3478422599,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 3600,\n            \"real_time\": 580271.5925448057,\n            \"cpu_time\": 577763.5555555568,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 704,\n            \"real_time\": 2952121.4191018688,\n            \"cpu_time\": 2933319.4772727196,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 8768,\n            \"real_time\": 237714.8166023336,\n            \"cpu_time\": 236736.05862226328,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2400,\n            \"real_time\": 906217.6969988892,\n            \"cpu_time\": 900408.9316666663,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1728,\n            \"real_time\": 1186305.3205161123,\n            \"cpu_time\": 1180928.2112268503,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 368,\n            \"real_time\": 5523193.665873765,\n            \"cpu_time\": 5489099.771739139,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 7616,\n            \"real_time\": 267911.83978168515,\n            \"cpu_time\": 266822.27113970637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2096,\n            \"real_time\": 998855.2242768964,\n            \"cpu_time\": 994254.3124999991,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"summing_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:10:04-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/summing_for_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            32.6357,\n            27.7808,\n            29.9585\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7033276,\n            \"real_time\": 289.6005293875894,\n            \"cpu_time\": 286.6507893334486,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7429,\n            \"real_time\": 290511.27474489785,\n            \"cpu_time\": 287605.8229909812,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73,\n            \"real_time\": 29084164.53442753,\n            \"cpu_time\": 28778812.05479452,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2171428,\n            \"real_time\": 972.5855519491528,\n            \"cpu_time\": 963.8436429851695,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1430115,\n            \"real_time\": 1488.2550375757246,\n            \"cpu_time\": 1472.903581879779,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1311525,\n            \"real_time\": 1483.3221227119222,\n            \"cpu_time\": 1468.1754827395603,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1300899,\n            \"real_time\": 1460.9917857122746,\n            \"cpu_time\": 1445.818111167739,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 983153,\n            \"real_time\": 1682.8524329387374,\n            \"cpu_time\": 1665.5108350378844,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 763038,\n            \"real_time\": 2503.0318058038574,\n            \"cpu_time\": 2482.6496504761235,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 670752,\n            \"real_time\": 3108.55554205422,\n            \"cpu_time\": 3076.1686510066324,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 605542,\n            \"real_time\": 3647.8771381501806,\n            \"cpu_time\": 3610.1070181754494,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 363236,\n            \"real_time\": 5588.595004288755,\n            \"cpu_time\": 5530.532642689597,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 285109,\n            \"real_time\": 7122.483113705193,\n            \"cpu_time\": 7046.989677632058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 194813,\n            \"real_time\": 10840.87867387822,\n            \"cpu_time\": 10735.134975591984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154940,\n            \"real_time\": 13560.40772585706,\n            \"cpu_time\": 13417.063392280912,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106261,\n            \"real_time\": 19682.850388074192,\n            \"cpu_time\": 19411.27936872421,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 82300,\n            \"real_time\": 25526.95345062251,\n            \"cpu_time\": 25181.76775212636,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5470,\n            \"real_time\": 717489.4180901389,\n            \"cpu_time\": 687431.0016453385,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_omp/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7321,\n            \"real_time\": 288138.7433443224,\n            \"cpu_time\": 285404.65756044234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_omp/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14178,\n            \"real_time\": 149156.19580228065,\n            \"cpu_time\": 147680.4265058542,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_omp/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20816,\n            \"real_time\": 101538.11962328898,\n            \"cpu_time\": 100514.195234435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_omp/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27062,\n            \"real_time\": 80622.18058496845,\n            \"cpu_time\": 79974.4904663365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_omp/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37754,\n            \"real_time\": 54114.126451600634,\n            \"cpu_time\": 53540.70906394019,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_omp/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51191,\n            \"real_time\": 41697.85632194792,\n            \"cpu_time\": 41251.9968549159,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_omp/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71393,\n            \"real_time\": 29361.131554399675,\n            \"cpu_time\": 29050.339529085548,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_omp/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86105,\n            \"real_time\": 24350.770617411286,\n            \"cpu_time\": 24094.66686022876,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_omp/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112277,\n            \"real_time\": 19143.750215746404,\n            \"cpu_time\": 18993.184917659077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_omp/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 121174,\n            \"real_time\": 17171.635391448555,\n            \"cpu_time\": 17014.967212438252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_omp/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127888,\n            \"real_time\": 16241.456883889328,\n            \"cpu_time\": 16022.947164706604,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_omp/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115736,\n            \"real_time\": 17921.592996339787,\n            \"cpu_time\": 17680.868096357233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_omp/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84590,\n            \"real_time\": 24163.647369464117,\n            \"cpu_time\": 23801.927201796912,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_omp/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68105,\n            \"real_time\": 30706.337758464862,\n            \"cpu_time\": 30288.407649952256,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_omp/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 346,\n            \"real_time\": 6100074.037831449,\n            \"cpu_time\": 5891347.99132949,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_omp/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 29233748.60481897,\n            \"cpu_time\": 28913179.22535203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_omp/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 15074987.069237975,\n            \"cpu_time\": 14951088.760000033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_omp/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 202,\n            \"real_time\": 10761478.990155024,\n            \"cpu_time\": 10661156.980198005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_omp/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 256,\n            \"real_time\": 8034382.125060801,\n            \"cpu_time\": 7975285.238281227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_omp/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 348,\n            \"real_time\": 5883168.166867276,\n            \"cpu_time\": 5839036.100574697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_omp/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 430,\n            \"real_time\": 5461308.927827537,\n            \"cpu_time\": 5430742.586046527,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_omp/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 525,\n            \"real_time\": 3949553.076222184,\n            \"cpu_time\": 3923306.234285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_omp/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 586,\n            \"real_time\": 3545358.6006352725,\n            \"cpu_time\": 3507802.011945404,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_omp/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1238,\n            \"real_time\": 2087736.1857679843,\n            \"cpu_time\": 2075735.2641357016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_omp/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1399,\n            \"real_time\": 1566006.9020447708,\n            \"cpu_time\": 1557100.819156544,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_omp/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2261,\n            \"real_time\": 1199778.177374245,\n            \"cpu_time\": 1188616.1291463976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_omp/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2155,\n            \"real_time\": 971301.5522323807,\n            \"cpu_time\": 951809.5614849151,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_omp/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2078,\n            \"real_time\": 999687.132860343,\n            \"cpu_time\": 981412.7641963473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_omp/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2671,\n            \"real_time\": 775406.6091334885,\n            \"cpu_time\": 758048.8487457864,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_omp/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321,\n            \"real_time\": 6689136.420634816,\n            \"cpu_time\": 6323196.560747653,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77899,\n            \"real_time\": 27029.055686918076,\n            \"cpu_time\": 26863.2201825443,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78124,\n            \"real_time\": 26593.643220746264,\n            \"cpu_time\": 26452.862667042024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83725,\n            \"real_time\": 25053.67035010068,\n            \"cpu_time\": 24848.897318602612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 89356,\n            \"real_time\": 23320.072440003114,\n            \"cpu_time\": 23122.75438694669,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94183,\n            \"real_time\": 21669.686142609415,\n            \"cpu_time\": 21490.176518055418,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98341,\n            \"real_time\": 21566.44191108164,\n            \"cpu_time\": 21384.292838185345,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97127,\n            \"real_time\": 20710.9944401379,\n            \"cpu_time\": 20582.003418205106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106647,\n            \"real_time\": 19528.43827800899,\n            \"cpu_time\": 19372.22315676962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105708,\n            \"real_time\": 20387.033166619127,\n            \"cpu_time\": 20238.545379725354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108928,\n            \"real_time\": 19180.09585213517,\n            \"cpu_time\": 19051.53801593731,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117190,\n            \"real_time\": 17874.46314575948,\n            \"cpu_time\": 17673.62018090268,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111514,\n            \"real_time\": 18881.773659865397,\n            \"cpu_time\": 18690.872123679535,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 118001,\n            \"real_time\": 18063.29994631622,\n            \"cpu_time\": 17854.540419148954,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114594,\n            \"real_time\": 18636.519660151513,\n            \"cpu_time\": 18438.519704347655,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 130954,\n            \"real_time\": 15784.488232148879,\n            \"cpu_time\": 15702.586274569612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5216,\n            \"real_time\": 403493.5163035475,\n            \"cpu_time\": 399940.27128067665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7413,\n            \"real_time\": 281568.274920703,\n            \"cpu_time\": 279377.6740860646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9496,\n            \"real_time\": 226901.44324902346,\n            \"cpu_time\": 225245.94839932726,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10715,\n            \"real_time\": 189875.47055606495,\n            \"cpu_time\": 188432.14596360122,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14154,\n            \"real_time\": 147836.1768384963,\n            \"cpu_time\": 146492.77864914513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17134,\n            \"real_time\": 121350.21547791566,\n            \"cpu_time\": 120757.69715186108,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21862,\n            \"real_time\": 96203.81804214139,\n            \"cpu_time\": 95625.67175921747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25669,\n            \"real_time\": 79544.09240476412,\n            \"cpu_time\": 79069.82278234468,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32922,\n            \"real_time\": 63400.96816572183,\n            \"cpu_time\": 63091.108954498886,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38540,\n            \"real_time\": 54578.12200274297,\n            \"cpu_time\": 54257.41027503959,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46825,\n            \"real_time\": 44730.19666766904,\n            \"cpu_time\": 44444.09095568562,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49911,\n            \"real_time\": 40597.999420023945,\n            \"cpu_time\": 40262.30492276257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54897,\n            \"real_time\": 39416.406270257234,\n            \"cpu_time\": 39007.322294478705,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50143,\n            \"real_time\": 39647.8976723195,\n            \"cpu_time\": 39068.90281794041,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 63437,\n            \"real_time\": 31362.84491624082,\n            \"cpu_time\": 31193.10544319532,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 30426905.39801055,\n            \"cpu_time\": 30135818.220588062,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 15246663.978489647,\n            \"cpu_time\": 15091213.985714294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 11014413.101560801,\n            \"cpu_time\": 10900200.994923832,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 263,\n            \"real_time\": 9347527.619883304,\n            \"cpu_time\": 9255603.596958125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 333,\n            \"real_time\": 7781236.132190146,\n            \"cpu_time\": 7688192.516516513,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 443,\n            \"real_time\": 4976691.158107875,\n            \"cpu_time\": 4952235.144469585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 653,\n            \"real_time\": 4627876.291065769,\n            \"cpu_time\": 4592960.987748828,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 677,\n            \"real_time\": 3230722.2953954907,\n            \"cpu_time\": 3208799.165435753,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 972,\n            \"real_time\": 1954722.5791987784,\n            \"cpu_time\": 1945143.972222224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1222,\n            \"real_time\": 1923923.2937901383,\n            \"cpu_time\": 1909759.2160392802,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1304,\n            \"real_time\": 1510703.3289669002,\n            \"cpu_time\": 1501449.4493864856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1332,\n            \"real_time\": 1445601.7815099622,\n            \"cpu_time\": 1430643.60735734,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1446,\n            \"real_time\": 1473428.5733698613,\n            \"cpu_time\": 1444303.8914246347,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1438,\n            \"real_time\": 1470118.0987582076,\n            \"cpu_time\": 1449616.0751043055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1333,\n            \"real_time\": 1550643.7367082636,\n            \"cpu_time\": 1529734.6624156036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6813835,\n            \"real_time\": 312.2187094366394,\n            \"cpu_time\": 308.9242138971678,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6741933,\n            \"real_time\": 316.2979850203427,\n            \"cpu_time\": 312.9422432705919,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6648567,\n            \"real_time\": 312.40136814247387,\n            \"cpu_time\": 309.0741801955225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6784117,\n            \"real_time\": 316.03588292738596,\n            \"cpu_time\": 312.9795066918793,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6834876,\n            \"real_time\": 311.8125822602392,\n            \"cpu_time\": 308.7055084832543,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6814073,\n            \"real_time\": 311.85363496150075,\n            \"cpu_time\": 308.49235251809296,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6384505,\n            \"real_time\": 324.74961020347183,\n            \"cpu_time\": 321.11364138644825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6416213,\n            \"real_time\": 321.6150838391804,\n            \"cpu_time\": 318.48866208151856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6569385,\n            \"real_time\": 314.4518922239314,\n            \"cpu_time\": 311.38552710793806,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6700929,\n            \"real_time\": 308.71024421408447,\n            \"cpu_time\": 305.7789282650154,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6359952,\n            \"real_time\": 326.7222974446451,\n            \"cpu_time\": 323.6671407268414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6436813,\n            \"real_time\": 325.99103796257043,\n            \"cpu_time\": 322.7346348262656,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5097786,\n            \"real_time\": 334.79385580396104,\n            \"cpu_time\": 331.36937329264106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6544437,\n            \"real_time\": 319.0686862685745,\n            \"cpu_time\": 315.68960187102266,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6114973,\n            \"real_time\": 334.6174949512944,\n            \"cpu_time\": 331.25296595749876,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7265,\n            \"real_time\": 294829.5416378372,\n            \"cpu_time\": 291299.09745354875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12836,\n            \"real_time\": 180554.71034606482,\n            \"cpu_time\": 178905.62028669738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15564,\n            \"real_time\": 135066.36860658586,\n            \"cpu_time\": 133878.42373425752,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19534,\n            \"real_time\": 106998.65823651476,\n            \"cpu_time\": 106024.1972458267,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27480,\n            \"real_time\": 76694.65946188818,\n            \"cpu_time\": 76092.45414846993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34649,\n            \"real_time\": 59949.48197379607,\n            \"cpu_time\": 59395.86028456848,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47903,\n            \"real_time\": 42594.567229894885,\n            \"cpu_time\": 42252.137173036244,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62865,\n            \"real_time\": 33992.32441036033,\n            \"cpu_time\": 33712.467159786414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76375,\n            \"real_time\": 33515.36892970289,\n            \"cpu_time\": 33301.47984288055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58686,\n            \"real_time\": 36247.07310039107,\n            \"cpu_time\": 36044.893722523004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48943,\n            \"real_time\": 35984.82354913241,\n            \"cpu_time\": 35763.16756226642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55725,\n            \"real_time\": 39487.31287752315,\n            \"cpu_time\": 39298.158833556896,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45740,\n            \"real_time\": 45378.84737672402,\n            \"cpu_time\": 44125.42284652371,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45065,\n            \"real_time\": 45672.658782108876,\n            \"cpu_time\": 43809.52728281372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31731,\n            \"real_time\": 65357.42835082342,\n            \"cpu_time\": 41752.81551164571,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 30539515.722517133,\n            \"cpu_time\": 30244700.6250001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122,\n            \"real_time\": 17494623.040681187,\n            \"cpu_time\": 17343563.2131148,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 169,\n            \"real_time\": 12720908.21879635,\n            \"cpu_time\": 12631621.7041422,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 9493494.662128285,\n            \"cpu_time\": 9409601.661971778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 311,\n            \"real_time\": 6979325.340785254,\n            \"cpu_time\": 6928421.823151183,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 378,\n            \"real_time\": 5389377.613682497,\n            \"cpu_time\": 5360781.431216878,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 579,\n            \"real_time\": 3741997.2607515273,\n            \"cpu_time\": 3721964.860103538,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 759,\n            \"real_time\": 3177839.2187480438,\n            \"cpu_time\": 3152666.2595520867,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1117,\n            \"real_time\": 1971023.717116408,\n            \"cpu_time\": 1958864.291853153,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1305,\n            \"real_time\": 1642503.5226647654,\n            \"cpu_time\": 1631554.1111111126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1346,\n            \"real_time\": 1485629.6122166845,\n            \"cpu_time\": 1476386.7696879506,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1375,\n            \"real_time\": 1475880.765779452,\n            \"cpu_time\": 1462092.3803636287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1442,\n            \"real_time\": 1484003.024248099,\n            \"cpu_time\": 1448193.2371706269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1278,\n            \"real_time\": 1520769.213689185,\n            \"cpu_time\": 1454218.9053207997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1131,\n            \"real_time\": 1796906.472967689,\n            \"cpu_time\": 1444540.6622457637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6453978,\n            \"real_time\": 325.4257228779304,\n            \"cpu_time\": 321.41128525694273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6369472,\n            \"real_time\": 319.8290745430692,\n            \"cpu_time\": 316.2148821754761,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6729237,\n            \"real_time\": 310.3229972493717,\n            \"cpu_time\": 307.2244781986371,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6748383,\n            \"real_time\": 331.60433425117617,\n            \"cpu_time\": 328.3737619812008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6478266,\n            \"real_time\": 320.5759981195779,\n            \"cpu_time\": 316.98289465113123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6433329,\n            \"real_time\": 306.55194130250015,\n            \"cpu_time\": 303.45384776683704,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6909464,\n            \"real_time\": 317.5174809449612,\n            \"cpu_time\": 314.42856001565394,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6405473,\n            \"real_time\": 329.5694516287644,\n            \"cpu_time\": 326.1713604912519,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5347013,\n            \"real_time\": 314.0967635656588,\n            \"cpu_time\": 310.8149974574577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6840035,\n            \"real_time\": 316.6223177214037,\n            \"cpu_time\": 313.4683642700632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6719048,\n            \"real_time\": 311.7035504186771,\n            \"cpu_time\": 308.56495101687534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6453383,\n            \"real_time\": 319.23694300827214,\n            \"cpu_time\": 316.0247288902556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/96/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6483954,\n            \"real_time\": 313.5667931994157,\n            \"cpu_time\": 310.3334406752373,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/128/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6585026,\n            \"real_time\": 325.52675873014454,\n            \"cpu_time\": 322.4094876770395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/192/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6050551,\n            \"real_time\": 336.86313858186264,\n            \"cpu_time\": 333.76717145264473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7300,\n            \"real_time\": 292628.43151092017,\n            \"cpu_time\": 289833.59534246987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11146,\n            \"real_time\": 208723.79983246405,\n            \"cpu_time\": 206224.48097972505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14366,\n            \"real_time\": 147059.0943147623,\n            \"cpu_time\": 145587.5348740066,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18959,\n            \"real_time\": 112557.42112160187,\n            \"cpu_time\": 111502.46278812163,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27050,\n            \"real_time\": 76244.85227408475,\n            \"cpu_time\": 75439.880073937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35377,\n            \"real_time\": 61173.72157027782,\n            \"cpu_time\": 60636.63741979167,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50023,\n            \"real_time\": 42669.4253641693,\n            \"cpu_time\": 42195.650300861606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60611,\n            \"real_time\": 33568.91410765407,\n            \"cpu_time\": 33306.890036461984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72420,\n            \"real_time\": 31834.72544910091,\n            \"cpu_time\": 31554.379384147353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72688,\n            \"real_time\": 36037.544821453186,\n            \"cpu_time\": 35863.068732115404,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52991,\n            \"real_time\": 35099.76265879266,\n            \"cpu_time\": 34928.830556132234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49380,\n            \"real_time\": 38603.01271936475,\n            \"cpu_time\": 38394.990319967634,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46196,\n            \"real_time\": 44454.5422326904,\n            \"cpu_time\": 43206.526257684985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46048,\n            \"real_time\": 45599.77664475108,\n            \"cpu_time\": 43493.72192060456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39566,\n            \"real_time\": 59920.02244433338,\n            \"cpu_time\": 42409.48655411146,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 29659182.95642912,\n            \"cpu_time\": 29344848.464788843,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 114,\n            \"real_time\": 20185865.39442798,\n            \"cpu_time\": 19964285.03508746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 148,\n            \"real_time\": 14181477.48650832,\n            \"cpu_time\": 14022770.013513297,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 189,\n            \"real_time\": 11011752.301812291,\n            \"cpu_time\": 10890893.560846502,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 281,\n            \"real_time\": 8740764.989159683,\n            \"cpu_time\": 8649685.729537332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 299,\n            \"real_time\": 6275556.896296158,\n            \"cpu_time\": 6222041.414715655,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 565,\n            \"real_time\": 4235458.746964557,\n            \"cpu_time\": 4197415.789380569,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 716,\n            \"real_time\": 3033479.55728418,\n            \"cpu_time\": 3011880.2346369103,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 917,\n            \"real_time\": 2336486.0709449896,\n            \"cpu_time\": 2318800.031624895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 924,\n            \"real_time\": 1663891.3214029302,\n            \"cpu_time\": 1650863.0346320572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 974,\n            \"real_time\": 1795355.3306105216,\n            \"cpu_time\": 1781564.9804928286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 983,\n            \"real_time\": 1783452.5920842923,\n            \"cpu_time\": 1767781.9226856458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_static/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1154,\n            \"real_time\": 1836896.2624770438,\n            \"cpu_time\": 1751382.8076256819,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_static/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1196,\n            \"real_time\": 1696131.775976411,\n            \"cpu_time\": 1564133.2357859882,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_static/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1169,\n            \"real_time\": 1769629.4405356597,\n            \"cpu_time\": 1465886.9606501462,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"timed_task_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:18:16-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/timed_task_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            34.7729,\n            33.062,\n            32.3589\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_dispenso<2,false>/manual_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 186.95238095227847,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0004919999999999994,\n            \"\\t1 System\": 0.0013039999999999996,\n            \"mean\": 2.7140469872392674e-05,\n            \"stddev\": 3.926980323384966e-05\n          },\n          {\n            \"name\": \"BM_dispenso<4,false>/manual_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 201.7619047619374,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.00011299999999999852,\n            \"\\t1 System\": 0.0018929999999999989,\n            \"mean\": 2.704811501316719e-05,\n            \"stddev\": 3.1390342298115365e-05\n          },\n          {\n            \"name\": \"BM_dispenso<6,false>/manual_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 199.33333333332254,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0001810000000000006,\n            \"\\t1 System\": 0.0021309999999999975,\n            \"mean\": 3.479623445309686e-05,\n            \"stddev\": 4.866726682928979e-05\n          },\n          {\n            \"name\": \"BM_dispenso<2,true>/manual_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 170.71428571430445,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0006359999999999994,\n            \"\\t1 System\": 0.0014449999999999984,\n            \"mean\": 3.315717534035652e-05,\n            \"stddev\": 4.4912856182945694e-05\n          },\n          {\n            \"name\": \"BM_dispenso<4,true>/manual_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 203.14285714282371,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0007479999999999987,\n            \"\\t1 System\": 0.0017489999999999936,\n            \"mean\": 3.5652824022868315e-05,\n            \"stddev\": 2.0879758342796617e-05\n          },\n          {\n            \"name\": \"BM_dispenso<6,true>/manual_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 195.52380952382134,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0005579999999999995,\n            \"\\t1 System\": 0.001341999999999996,\n            \"mean\": 2.1994207497414084e-05,\n            \"stddev\": 1.9398465095117333e-05\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 198.85714285721747,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0006040000000000004,\n            \"\\t1 System\": 0.001240000000000005,\n            \"mean\": 5.729239188755512e-06,\n            \"stddev\": 5.818560816710941e-06\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 116.38095238098815,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0008389999999999995,\n            \"\\t1 System\": 0.0016420000000000046,\n            \"mean\": 1.3252527364395848e-05,\n            \"stddev\": 3.167401925688938e-05\n          },\n          {\n            \"name\": \"BM_folly<2,false>/manual_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 101.57142857132926,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0009779999999999997,\n            \"\\t1 System\": 0.0018740000000000007,\n            \"mean\": 9.506486796773933e-05,\n            \"stddev\": 0.00014178820903420984\n          },\n          {\n            \"name\": \"BM_folly<4,false>/manual_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 108.76190476198578,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0012110000000000037,\n            \"\\t1 System\": 0.0017070000000000002,\n            \"mean\": 9.695655324961982e-05,\n            \"stddev\": 0.00027012745352402546\n          },\n          {\n            \"name\": \"BM_folly<6,false>/manual_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 181.71428571429695,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.001571000000000003,\n            \"\\t1 System\": 0.0017370000000000024,\n            \"mean\": 0.00011235004855785578,\n            \"stddev\": 0.00041143148170906773\n          },\n          {\n            \"name\": \"BM_folly<2,true>/manual_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 164.04761904767736,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0010410000000000003,\n            \"\\t1 System\": 0.001894999999999994,\n            \"mean\": 9.362332498862681e-05,\n            \"stddev\": 5.742038248369901e-05\n          },\n          {\n            \"name\": \"BM_folly<4,true>/manual_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 177.42857142869073,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0012819999999999984,\n            \"\\t1 System\": 0.002370999999999998,\n            \"mean\": 9.366584334868824e-05,\n            \"stddev\": 6.205024556313576e-06\n          },\n          {\n            \"name\": \"BM_folly<6,true>/manual_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 184.09523809515258,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0019340000000000052,\n            \"\\t1 System\": 0.0009679999999999966,\n            \"mean\": 7.875578021719309e-05,\n            \"stddev\": 3.058280796108715e-05\n          },\n          {\n            \"name\": \"BM_folly_mixed<false>/manual_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 187.90476190465375,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0,\n            \"\\t1 System\": 0.004200999999999996,\n            \"mean\": 6.519594988630389e-05,\n            \"stddev\": 0.00019775921061042866\n          },\n          {\n            \"name\": \"BM_folly_mixed<true>/manual_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 100000000.00000003,\n            \"cpu_time\": 168.3333333332836,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0009400000000000033,\n            \"\\t1 System\": 0.0015539999999999998,\n            \"mean\": 5.960014752544842e-05,\n            \"stddev\": 3.91825259550134e-06\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"trivial_compute_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:18:55-07:00\",\n          \"host_name\": \"linux-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/trivial_compute_benchmark\",\n          \"num_cpus\": 192,\n          \"mhz_per_cpu\": 5190,\n          \"cpu_scaling_enabled\": true,\n          \"aslr_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 33554432,\n              \"num_sharing\": 16\n            }\n          ],\n          \"load_avg\": [\n            18.6284,\n            29.1445,\n            31.0713\n          ],\n          \"library_version\": \"1.9.4\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1523208,\n            \"real_time\": 1416.0441653309208,\n            \"cpu_time\": 1400.504979621956,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 51863849.75648962,\n            \"cpu_time\": 51249909.17073169,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1399299244.4545963,\n            \"cpu_time\": 1384836423.0000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_omp/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1012595,\n            \"real_time\": 2090.2514677630497,\n            \"cpu_time\": 2069.3704649934084,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_omp/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 968783,\n            \"real_time\": 2142.0910936523483,\n            \"cpu_time\": 2119.005957990591,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_omp/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 789450,\n            \"real_time\": 2235.182444719835,\n            \"cpu_time\": 2210.6305643169335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_omp/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1137878,\n            \"real_time\": 1921.9938130546711,\n            \"cpu_time\": 1903.3675253410295,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_omp/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 763445,\n            \"real_time\": 2187.5988356598546,\n            \"cpu_time\": 2165.7814276077534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_omp/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1097299,\n            \"real_time\": 2685.5481395255333,\n            \"cpu_time\": 2656.803469245848,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_omp/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 644711,\n            \"real_time\": 3253.1471155468093,\n            \"cpu_time\": 3228.694067574461,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_omp/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 495949,\n            \"real_time\": 4338.474365387438,\n            \"cpu_time\": 4315.419258835082,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_omp/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 319432,\n            \"real_time\": 6456.13749719944,\n            \"cpu_time\": 6431.124818427719,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_omp/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 251445,\n            \"real_time\": 7778.469836066934,\n            \"cpu_time\": 7746.477193819722,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_omp/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200697,\n            \"real_time\": 10413.30787204524,\n            \"cpu_time\": 10342.284304199886,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_omp/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154783,\n            \"real_time\": 13430.334520099297,\n            \"cpu_time\": 13338.92497884132,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_omp/96/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 106449,\n            \"real_time\": 19702.18571359484,\n            \"cpu_time\": 19488.308344841185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_omp/128/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79916,\n            \"real_time\": 26262.325690816368,\n            \"cpu_time\": 25985.26057360231,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_omp/192/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 349,\n            \"real_time\": 6148972.6933130305,\n            \"cpu_time\": 6025782.974212033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_omp/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 49584102.14333396,\n            \"cpu_time\": 49094705.7380952,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_omp/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 42985081.08108856,\n            \"cpu_time\": 42607553.14285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_omp/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 28435189.70864049,\n            \"cpu_time\": 28198909.208333332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_omp/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97,\n            \"real_time\": 21895593.45349631,\n            \"cpu_time\": 21646007.855670117,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_omp/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 14841395.59241677,\n            \"cpu_time\": 14740509.03571426,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_omp/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 185,\n            \"real_time\": 11266212.746173747,\n            \"cpu_time\": 11194047.545945993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_omp/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 273,\n            \"real_time\": 7575781.794602645,\n            \"cpu_time\": 7386770.732600722,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_omp/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 371,\n            \"real_time\": 5653712.32614363,\n            \"cpu_time\": 5430837.948787036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_omp/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 559,\n            \"real_time\": 3786611.1127126543,\n            \"cpu_time\": 3747933.266547413,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_omp/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 742,\n            \"real_time\": 2840537.340957621,\n            \"cpu_time\": 2820410.8153638775,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_omp/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1043,\n            \"real_time\": 2011657.779440748,\n            \"cpu_time\": 1989024.4506232052,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_omp/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1315,\n            \"real_time\": 1558994.9003856333,\n            \"cpu_time\": 1533465.5977186318,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_omp/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1747,\n            \"real_time\": 1215047.6416775505,\n            \"cpu_time\": 1196050.192902118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_omp/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2070,\n            \"real_time\": 1001926.9168988806,\n            \"cpu_time\": 988499.1207729415,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_omp/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 341,\n            \"real_time\": 6245890.788971569,\n            \"cpu_time\": 6026429.932551304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_omp/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1415209950.9956315,\n            \"cpu_time\": 1400618604.4999964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_omp/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 726854279.016455,\n            \"cpu_time\": 719282241.3333365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_omp/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 508420653.0009396,\n            \"cpu_time\": 503326072.50000197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_omp/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 388268271.39128,\n            \"cpu_time\": 384567867.99999917,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_omp/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 275552845.5018066,\n            \"cpu_time\": 273136380.9999987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_omp/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 217170940.793585,\n            \"cpu_time\": 215307868.00000072,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_omp/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 157498503.0769872,\n            \"cpu_time\": 155963612.84615386,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_omp/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 128075455.58248152,\n            \"cpu_time\": 127144504.29411653,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_omp/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 97735861.54915394,\n            \"cpu_time\": 97060084.90908986,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_omp/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 82937143.76166463,\n            \"cpu_time\": 82192940.31999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_omp/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 70971454.56743117,\n            \"cpu_time\": 70333687.50000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_omp/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 64620135.34473954,\n            \"cpu_time\": 64139035.37499976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/96/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_omp/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 59362319.13640061,\n            \"cpu_time\": 58728417.749999866,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/128/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_omp/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 55723424.43141482,\n            \"cpu_time\": 55229560.540540606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_omp/192/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_omp/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 58871815.69252991,\n            \"cpu_time\": 53250691.61111095,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 245398,\n            \"real_time\": 8696.457077940235,\n            \"cpu_time\": 8627.040049226194,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 225258,\n            \"real_time\": 9725.35110363063,\n            \"cpu_time\": 9656.276700494433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 208371,\n            \"real_time\": 10349.578688842974,\n            \"cpu_time\": 10277.122065930505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 199733,\n            \"real_time\": 10422.62069369878,\n            \"cpu_time\": 10357.318835645638,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180951,\n            \"real_time\": 11400.623008853066,\n            \"cpu_time\": 11336.305917071422,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 170508,\n            \"real_time\": 12341.240041609353,\n            \"cpu_time\": 12273.924865695359,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 155681,\n            \"real_time\": 13488.799352548083,\n            \"cpu_time\": 13420.504550972837,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 139040,\n            \"real_time\": 15118.654041821126,\n            \"cpu_time\": 15043.788672324488,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 126582,\n            \"real_time\": 16057.454124670176,\n            \"cpu_time\": 15982.92271413005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 129424,\n            \"real_time\": 16331.867219594173,\n            \"cpu_time\": 16229.59910063061,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125472,\n            \"real_time\": 16659.770673448176,\n            \"cpu_time\": 16564.08864129051,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 126445,\n            \"real_time\": 16829.03621358427,\n            \"cpu_time\": 16710.532231404955,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/96/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117053,\n            \"real_time\": 17800.632064203106,\n            \"cpu_time\": 17676.1360323954,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/128/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108149,\n            \"real_time\": 18587.926018693677,\n            \"cpu_time\": 18410.4145207076,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/192/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100000,\n            \"real_time\": 15276.640580268577,\n            \"cpu_time\": 15216.156300000135,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 49410317.42491759,\n            \"cpu_time\": 48927933.02499996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 25674075.201442022,\n            \"cpu_time\": 25401190.9166668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 17174998.41939688,\n            \"cpu_time\": 16989779.95967736,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 13252048.701863527,\n            \"cpu_time\": 13125491.894409815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 239,\n            \"real_time\": 8928044.167226452,\n            \"cpu_time\": 8851881.598326348,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 310,\n            \"real_time\": 6789485.354637426,\n            \"cpu_time\": 6713146.996774214,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 461,\n            \"real_time\": 4546968.570663927,\n            \"cpu_time\": 4504427.32971801,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 611,\n            \"real_time\": 3428122.7447293736,\n            \"cpu_time\": 3397211.613747937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 886,\n            \"real_time\": 2388410.036200889,\n            \"cpu_time\": 2367728.8340857676,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1063,\n            \"real_time\": 1803849.158026208,\n            \"cpu_time\": 1791970.6810912725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1650,\n            \"real_time\": 1271657.4115311783,\n            \"cpu_time\": 1260045.795757578,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1967,\n            \"real_time\": 1033947.1428803285,\n            \"cpu_time\": 1019400.6075241397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2447,\n            \"real_time\": 790595.2599505514,\n            \"cpu_time\": 778905.9967307068,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3078,\n            \"real_time\": 643282.8781693627,\n            \"cpu_time\": 633753.672839511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3287,\n            \"real_time\": 571341.3915533718,\n            \"cpu_time\": 566995.0827502221,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1352936672.9781032,\n            \"cpu_time\": 1339353317.4999845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 687719183.3142812,\n            \"cpu_time\": 681235153.999997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 460955460.4161531,\n            \"cpu_time\": 456367995.1999916,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 349988193.5034258,\n            \"cpu_time\": 346785318.6666711,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 236514067.44546774,\n            \"cpu_time\": 234416387.77777976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 179268747.91737643,\n            \"cpu_time\": 178150068.16666803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 119136739.16650522,\n            \"cpu_time\": 118613408.27777806,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 89829074.17837693,\n            \"cpu_time\": 88917691.95652258,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 61243230.12067401,\n            \"cpu_time\": 60863498.15151517,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 46501795.10936141,\n            \"cpu_time\": 46053554.733332984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 32990284.24155568,\n            \"cpu_time\": 32689259.93548387,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74,\n            \"real_time\": 27317037.134167008,\n            \"cpu_time\": 26875710.027027436,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/96/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_tbb/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 21736599.171576515,\n            \"cpu_time\": 21413873.693181787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_tbb/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 20283679.438669387,\n            \"cpu_time\": 19967876.234693564,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/192/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_tbb/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 18457328.223962788,\n            \"cpu_time\": 18334807.17757018,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1540077,\n            \"real_time\": 1350.67698304802,\n            \"cpu_time\": 1337.4727568816243,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1520067,\n            \"real_time\": 1376.2797238766152,\n            \"cpu_time\": 1363.0110541180034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1521971,\n            \"real_time\": 1405.6027138750324,\n            \"cpu_time\": 1392.2947092947334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1466336,\n            \"real_time\": 1411.29718495238,\n            \"cpu_time\": 1398.8675835552256,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1480130,\n            \"real_time\": 1379.7596765673707,\n            \"cpu_time\": 1366.5290920392229,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1515782,\n            \"real_time\": 1364.417215676475,\n            \"cpu_time\": 1352.1715833807439,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1538244,\n            \"real_time\": 1376.6631367391433,\n            \"cpu_time\": 1363.4847533941036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1533359,\n            \"real_time\": 1356.6830931164197,\n            \"cpu_time\": 1343.7240111415474,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1541843,\n            \"real_time\": 1400.5808996084356,\n            \"cpu_time\": 1386.1807732693994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1515045,\n            \"real_time\": 1375.2972452727515,\n            \"cpu_time\": 1361.612895326562,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1531630,\n            \"real_time\": 1358.0364768211948,\n            \"cpu_time\": 1345.675417039369,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1503924,\n            \"real_time\": 1489.0797786133835,\n            \"cpu_time\": 1471.7609307385173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/96/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1376750,\n            \"real_time\": 1509.090866917206,\n            \"cpu_time\": 1490.8966435445643,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/128/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1369547,\n            \"real_time\": 1442.3813020266336,\n            \"cpu_time\": 1427.726892906934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/192/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000,\n            \"real_time\": 1551.350254099816,\n            \"cpu_time\": 1535.569976999966,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 52309520.02429625,\n            \"cpu_time\": 51850072.42857187,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 25377341.58353747,\n            \"cpu_time\": 25104058.250000045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 17288701.50832189,\n            \"cpu_time\": 17168201.8387099,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 163,\n            \"real_time\": 12858173.644250156,\n            \"cpu_time\": 12741047.95705532,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 241,\n            \"real_time\": 8666508.236447835,\n            \"cpu_time\": 8597964.016597318,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 317,\n            \"real_time\": 6623211.646546559,\n            \"cpu_time\": 6597018.356466965,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 477,\n            \"real_time\": 4426180.934914206,\n            \"cpu_time\": 4400447.607966522,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 637,\n            \"real_time\": 3309469.7488249633,\n            \"cpu_time\": 3286693.2951334934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 938,\n            \"real_time\": 2254618.149348048,\n            \"cpu_time\": 2245299.8507462377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1251,\n            \"real_time\": 1715786.9304059078,\n            \"cpu_time\": 1708821.4148681327,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1662,\n            \"real_time\": 1288945.7159792213,\n            \"cpu_time\": 1279018.4386281474,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1860,\n            \"real_time\": 1154805.4747543826,\n            \"cpu_time\": 1147386.7989247344,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2046,\n            \"real_time\": 1016670.1793926472,\n            \"cpu_time\": 1006607.0107526844,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2063,\n            \"real_time\": 1028019.4289966971,\n            \"cpu_time\": 991173.6330586642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2282,\n            \"real_time\": 1019556.6713891589,\n            \"cpu_time\": 579599.7081507451,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1375330757.5243526,\n            \"cpu_time\": 1362281440.0000038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 714575235.3438487,\n            \"cpu_time\": 707314986.9999989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 489631742.5009329,\n            \"cpu_time\": 484960246.2499973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 369329597.1606858,\n            \"cpu_time\": 365649416.6666656,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 249211537.62261385,\n            \"cpu_time\": 246951456.87499577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 188320188.45502964,\n            \"cpu_time\": 186982892.8181815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 125901212.70349139,\n            \"cpu_time\": 124775465.23529233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 94574359.67950997,\n            \"cpu_time\": 93941981.3636355,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 63193635.940975085,\n            \"cpu_time\": 62795187.45454673,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 48424842.29646454,\n            \"cpu_time\": 48023253.52272615,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 34063354.33734761,\n            \"cpu_time\": 33797558.661290385,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 27665412.932013474,\n            \"cpu_time\": 27514523.98666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/96/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87,\n            \"real_time\": 22667969.424470235,\n            \"cpu_time\": 22224155.747125976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/128/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 96,\n            \"real_time\": 20711409.05294063,\n            \"cpu_time\": 19136049.989583626,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/192/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 19291527.787263088,\n            \"cpu_time\": 9350254.37234059,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1550119,\n            \"real_time\": 1352.2557680793004,\n            \"cpu_time\": 1339.1977274002654,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1520325,\n            \"real_time\": 1391.5909802295155,\n            \"cpu_time\": 1377.8263226612848,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1529117,\n            \"real_time\": 1354.5879569754877,\n            \"cpu_time\": 1341.4574404705374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1524768,\n            \"real_time\": 1360.7380657523797,\n            \"cpu_time\": 1348.0249460901684,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1506598,\n            \"real_time\": 1388.3970707586252,\n            \"cpu_time\": 1375.0157653202634,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1539875,\n            \"real_time\": 1376.0296043184867,\n            \"cpu_time\": 1361.9473976783156,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1527277,\n            \"real_time\": 1374.781769773679,\n            \"cpu_time\": 1361.6601867244792,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1542880,\n            \"real_time\": 1370.6347836424854,\n            \"cpu_time\": 1357.5021971896783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1541071,\n            \"real_time\": 1357.6648681617432,\n            \"cpu_time\": 1344.7692319172859,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1527664,\n            \"real_time\": 1410.932275640563,\n            \"cpu_time\": 1397.3813469454299,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1471512,\n            \"real_time\": 1391.970121875155,\n            \"cpu_time\": 1378.4329254535287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1499272,\n            \"real_time\": 1422.5686900330093,\n            \"cpu_time\": 1408.3449634222607,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/96/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1499654,\n            \"real_time\": 1429.9213724946023,\n            \"cpu_time\": 1414.4340907968858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/128/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1499804,\n            \"real_time\": 1393.9271357851717,\n            \"cpu_time\": 1380.0509239874332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/100/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/192/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1368618,\n            \"real_time\": 1465.320160924836,\n            \"cpu_time\": 1450.2391770384377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 49874548.02328504,\n            \"cpu_time\": 49392520.65116497,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 43891043.56232565,\n            \"cpu_time\": 43501532.54166619,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 28959867.75734595,\n            \"cpu_time\": 28674475.528571617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 22328812.616599843,\n            \"cpu_time\": 22144520.765956994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 142,\n            \"real_time\": 14922498.162134064,\n            \"cpu_time\": 14794372.76056397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 181,\n            \"real_time\": 11527047.253944473,\n            \"cpu_time\": 11431555.988950407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 268,\n            \"real_time\": 7914033.84698527,\n            \"cpu_time\": 7849829.712686595,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 348,\n            \"real_time\": 6030756.399442239,\n            \"cpu_time\": 5976595.037356254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 517,\n            \"real_time\": 4112708.8799445783,\n            \"cpu_time\": 4081099.332688741,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 673,\n            \"real_time\": 3116670.5692098383,\n            \"cpu_time\": 3099256.582466622,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 932,\n            \"real_time\": 2217676.7628472056,\n            \"cpu_time\": 2200068.888412056,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1047,\n            \"real_time\": 1987768.8414857518,\n            \"cpu_time\": 1969186.4202483275,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static/96/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1725,\n            \"real_time\": 1219981.8104019633,\n            \"cpu_time\": 1207501.3350724238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static/128/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2041,\n            \"real_time\": 1021234.3581415993,\n            \"cpu_time\": 999980.4414502598,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static/192/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2359,\n            \"real_time\": 1047544.2899650042,\n            \"cpu_time\": 656721.2806273677,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1400449966.4879403,\n            \"cpu_time\": 1386203524.4999902,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 716108810.3118042,\n            \"cpu_time\": 708907762.3333348,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 495606920.24533635,\n            \"cpu_time\": 490731209.74998116,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 382006934.1920316,\n            \"cpu_time\": 378433778.3999945,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 272568132.7428902,\n            \"cpu_time\": 269967478.24999547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 212223990.7970652,\n            \"cpu_time\": 210775678.00000453,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 36,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 154803629.57376722,\n            \"cpu_time\": 153555378.92856675,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 37,\n            \"run_name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 124495087.29418193,\n            \"cpu_time\": 123650215.88235484,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 38,\n            \"run_name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 96962730.95588285,\n            \"cpu_time\": 96418408.9090891,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 39,\n            \"run_name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26,\n            \"real_time\": 81671621.1534535,\n            \"cpu_time\": 80951839.30769369,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 40,\n            \"run_name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 69209764.06739403,\n            \"cpu_time\": 68238638.96666656,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 41,\n            \"run_name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 64171457.09168505,\n            \"cpu_time\": 63562325.909091756,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/96/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 42,\n            \"run_name\": \"BM_dispenso_static/96/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 58501602.444771886,\n            \"cpu_time\": 57614121.77777616,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 43,\n            \"run_name\": \"BM_dispenso_static/128/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 55537981.18336616,\n            \"cpu_time\": 54743961.842105865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/192/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 44,\n            \"run_name\": \"BM_dispenso_static/192/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 53031581.40159212,\n            \"cpu_time\": 48024890.07499844,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    }\n  ]\n}"
  },
  {
    "path": "results/macos_arm64.json",
    "content": "{\n  \"machine_info\": {\n    \"timestamp\": \"2026-03-20T10:21:46.312656\",\n    \"platform\": \"Darwin\",\n    \"platform_release\": \"25.3.0\",\n    \"platform_version\": \"Darwin Kernel Version 25.3.0: Wed Jan 28 20:51:28 PST 2026; root:xnu-12377.91.3~2/RELEASE_ARM64_T6041\",\n    \"architecture\": \"arm64\",\n    \"processor\": \"arm\",\n    \"python_version\": \"3.12.13\",\n    \"cpu_model\": \"Apple M4 Pro\",\n    \"cpu_cores\": 12,\n    \"memory_gb\": 48.0,\n    \"platform_id\": \"macos-m4-pro-12c\",\n    \"compiler\": {\n      \"compiler_path\": \"/usr/bin/c++\",\n      \"build_type\": \"Release\",\n      \"cxx_standard\": \"20\",\n      \"compiler_id\": \"AppleClang\",\n      \"compiler_version\": \"17.0.0.17000604\",\n      \"compiler_summary\": \"AppleClang 17.0.0.17000604 Release C++20\"\n    }\n  },\n  \"results\": [\n    {\n      \"name\": \"cascading_parallel_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:21:48-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/cascading_parallel_for_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            2.18408,\n            2.60107,\n            2.58154\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1009403,\n            \"real_time\": 700.5002372642518,\n            \"cpu_time\": 700.4070722991706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/100000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8537,\n            \"real_time\": 82564.75728780165,\n            \"cpu_time\": 82556.16727187534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/10000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 10531123.778919743,\n            \"cpu_time\": 10528676.470588233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17360,\n            \"real_time\": 40468.82442649334,\n            \"cpu_time\": 40462.61520737326,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16325,\n            \"real_time\": 42482.3762312714,\n            \"cpu_time\": 42478.223583460924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15576,\n            \"real_time\": 45956.75770636757,\n            \"cpu_time\": 45920.45454545456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15275,\n            \"real_time\": 45833.22422490524,\n            \"cpu_time\": 45820.294599018016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15034,\n            \"real_time\": 46524.635821323674,\n            \"cpu_time\": 46501.52986563801,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13934,\n            \"real_time\": 48438.211717099184,\n            \"cpu_time\": 48365.4370604277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12357,\n            \"real_time\": 56151.88080459915,\n            \"cpu_time\": 56032.77494537507,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3636,\n            \"real_time\": 194204.43730386806,\n            \"cpu_time\": 194174.9174917493,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4678,\n            \"real_time\": 143290.9542392476,\n            \"cpu_time\": 143264.00171013267,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5580,\n            \"real_time\": 127191.27097948182,\n            \"cpu_time\": 127174.55197132606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6136,\n            \"real_time\": 116269.12205482468,\n            \"cpu_time\": 116217.07953063888,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6302,\n            \"real_time\": 111341.52506072912,\n            \"cpu_time\": 111328.78451285306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6516,\n            \"real_time\": 106468.23834384317,\n            \"cpu_time\": 106296.1939840391,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6204,\n            \"real_time\": 113265.23871415642,\n            \"cpu_time\": 112475.66086395872,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 13662088.23552976,\n            \"cpu_time\": 13660882.352941204,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87,\n            \"real_time\": 7987072.793017516,\n            \"cpu_time\": 7986735.63218397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115,\n            \"real_time\": 5930657.608879972,\n            \"cpu_time\": 5930313.043478278,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127,\n            \"real_time\": 5149498.361888833,\n            \"cpu_time\": 5149228.346456695,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 145,\n            \"real_time\": 4815002.013768615,\n            \"cpu_time\": 4814889.655172417,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 147,\n            \"real_time\": 4719341.271968723,\n            \"cpu_time\": 4719340.136054431,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 145,\n            \"real_time\": 4786840.799778444,\n            \"cpu_time\": 4726793.103448252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14797,\n            \"real_time\": 46310.25147244597,\n            \"cpu_time\": 46307.29201865246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19841,\n            \"real_time\": 36138.46328049984,\n            \"cpu_time\": 36051.66070258557,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22802,\n            \"real_time\": 31020.54828164434,\n            \"cpu_time\": 31016.27050258759,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24067,\n            \"real_time\": 29387.4583047368,\n            \"cpu_time\": 29331.699006939027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26880,\n            \"real_time\": 26002.083333358834,\n            \"cpu_time\": 25988.98809523811,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27278,\n            \"real_time\": 28964.18050935298,\n            \"cpu_time\": 28704.74374954171,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26855,\n            \"real_time\": 25367.38346523467,\n            \"cpu_time\": 25139.713274995338,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3660,\n            \"real_time\": 191380.60106839883,\n            \"cpu_time\": 191369.67213114686,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5831,\n            \"real_time\": 119517.87857815709,\n            \"cpu_time\": 119418.79608986464,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6832,\n            \"real_time\": 104196.9531729645,\n            \"cpu_time\": 103205.64988290385,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8266,\n            \"real_time\": 86986.97978760907,\n            \"cpu_time\": 86909.02492136456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10208,\n            \"real_time\": 69326.33316816197,\n            \"cpu_time\": 69302.31191222604,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11253,\n            \"real_time\": 63590.45366329318,\n            \"cpu_time\": 63475.78423531484,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11532,\n            \"real_time\": 61339.696066824254,\n            \"cpu_time\": 60693.895248005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 13977541.660424324,\n            \"cpu_time\": 13976599.999999875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 8006809.658995322,\n            \"cpu_time\": 8006340.909090894,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115,\n            \"real_time\": 5897592.034433847,\n            \"cpu_time\": 5896930.434782633,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 138,\n            \"real_time\": 5095387.384653145,\n            \"cpu_time\": 5095043.478260828,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4709900.731858391,\n            \"cpu_time\": 4709778.523489985,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 4616176.873747728,\n            \"cpu_time\": 4608761.58940393,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 152,\n            \"real_time\": 4597889.256394027,\n            \"cpu_time\": 4523861.842105257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1132922,\n            \"real_time\": 625.2072446734195,\n            \"cpu_time\": 625.1789620115105,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1148008,\n            \"real_time\": 609.6258327131047,\n            \"cpu_time\": 609.519271642708,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1151119,\n            \"real_time\": 614.8547995581773,\n            \"cpu_time\": 614.806114745739,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1132890,\n            \"real_time\": 619.0147180562062,\n            \"cpu_time\": 618.8720881992047,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1140663,\n            \"real_time\": 615.6145224666849,\n            \"cpu_time\": 615.4788925388102,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1128116,\n            \"real_time\": 615.83017610162,\n            \"cpu_time\": 615.4934421637473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1128179,\n            \"real_time\": 616.0202263334468,\n            \"cpu_time\": 615.3571374755221,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8183,\n            \"real_time\": 85654.28327098917,\n            \"cpu_time\": 85646.82879139687,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16044,\n            \"real_time\": 42077.09785398746,\n            \"cpu_time\": 41974.632261281724,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12694,\n            \"real_time\": 45516.625336456906,\n            \"cpu_time\": 45276.90247360959,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23536,\n            \"real_time\": 28130.824395788124,\n            \"cpu_time\": 27954.36777702262,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 51310.06670417264,\n            \"cpu_time\": 48782.20000000084,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12192,\n            \"real_time\": 69758.33538707634,\n            \"cpu_time\": 61748.60564304475,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8503,\n            \"real_time\": 74868.07102310973,\n            \"cpu_time\": 67074.56191932177,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67,\n            \"real_time\": 10497190.92526487,\n            \"cpu_time\": 10494850.746268587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 6129634.956029796,\n            \"cpu_time\": 6126274.336283213,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 119,\n            \"real_time\": 5701286.0676931115,\n            \"cpu_time\": 5668521.008403306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 133,\n            \"real_time\": 4770311.714269053,\n            \"cpu_time\": 4766932.330827085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 139,\n            \"real_time\": 4712284.769588184,\n            \"cpu_time\": 4703107.91366905,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4715272.09417932,\n            \"cpu_time\": 4663530.201342265,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5178351.670037955,\n            \"cpu_time\": 4897049.999999937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1159713,\n            \"real_time\": 605.3549102323939,\n            \"cpu_time\": 605.2713041933633,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1141338,\n            \"real_time\": 617.2509080811373,\n            \"cpu_time\": 616.7787281243642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1138697,\n            \"real_time\": 613.3981068106079,\n            \"cpu_time\": 613.125352925316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1150036,\n            \"real_time\": 612.0413117420418,\n            \"cpu_time\": 611.9669297309006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1142076,\n            \"real_time\": 617.5104589566071,\n            \"cpu_time\": 617.2286257657076,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1143504,\n            \"real_time\": 613.3846055813841,\n            \"cpu_time\": 613.2772600707987,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1134948,\n            \"real_time\": 612.7556064463755,\n            \"cpu_time\": 612.4016254489155,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8205,\n            \"real_time\": 85467.14405634196,\n            \"cpu_time\": 85462.64472882435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8841,\n            \"real_time\": 79109.74436570091,\n            \"cpu_time\": 79101.57222033705,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18115,\n            \"real_time\": 39438.96633034339,\n            \"cpu_time\": 39264.80817002547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28039,\n            \"real_time\": 24877.132421022685,\n            \"cpu_time\": 24874.78155426358,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20730,\n            \"real_time\": 33889.15822521801,\n            \"cpu_time\": 33831.59671972992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21317,\n            \"real_time\": 33917.59121880441,\n            \"cpu_time\": 33327.625838532964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13527,\n            \"real_time\": 52009.26850175269,\n            \"cpu_time\": 46971.53840467123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 10221724.044126661,\n            \"cpu_time\": 10220086.956521705,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86,\n            \"real_time\": 8297997.093651184,\n            \"cpu_time\": 8296639.5348836845,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127,\n            \"real_time\": 5467769.354361836,\n            \"cpu_time\": 5467338.582677238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 152,\n            \"real_time\": 4694495.618184048,\n            \"cpu_time\": 4693171.052631603,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 4577143.490160292,\n            \"cpu_time\": 4576741.721854356,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 155,\n            \"real_time\": 4465798.116589506,\n            \"cpu_time\": 4463890.3225806225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4684942.952613503,\n            \"cpu_time\": 4616798.657718159,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"concurrent_vector_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:23:10-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/concurrent_vector_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            5.05566,\n            3.44775,\n            2.9082\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_std_push_back_serial\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2213,\n            \"real_time\": 317631.75918000605,\n            \"cpu_time\": 317622.6841391777,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_push_back_serial\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1153,\n            \"real_time\": 614917.6790694814,\n            \"cpu_time\": 614874.2411101472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 368,\n            \"real_time\": 1901861.0733125925,\n            \"cpu_time\": 1901769.0217391297,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370,\n            \"real_time\": 1892992.4542159848,\n            \"cpu_time\": 1888705.4054054045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 202,\n            \"real_time\": 3386122.935871123,\n            \"cpu_time\": 3385905.940594063,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2691,\n            \"real_time\": 264930.2924185471,\n            \"cpu_time\": 263694.90895577834,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_push_back_serial_reserve\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2662,\n            \"real_time\": 261712.85686013865,\n            \"cpu_time\": 261686.32607062408,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_reserve\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370,\n            \"real_time\": 1891775.1136688967,\n            \"cpu_time\": 1891678.3783783778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 382,\n            \"real_time\": 1833904.557434735,\n            \"cpu_time\": 1833706.8062827229,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 201,\n            \"real_time\": 3402468.0794369592,\n            \"cpu_time\": 3402218.905472632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2693,\n            \"real_time\": 259512.3623864711,\n            \"cpu_time\": 259490.5310063132,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17821,\n            \"real_time\": 39443.283205270054,\n            \"cpu_time\": 39439.59373772512,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2421,\n            \"real_time\": 290307.6555123664,\n            \"cpu_time\": 290290.78893019445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1054,\n            \"real_time\": 666610.9269613884,\n            \"cpu_time\": 666577.7988614794,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1336,\n            \"real_time\": 516669.6923579964,\n            \"cpu_time\": 516152.694610778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate_reverse\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10788,\n            \"real_time\": 64897.47868062467,\n            \"cpu_time\": 64894.69781238416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate_reverse\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2366,\n            \"real_time\": 295664.90570821706,\n            \"cpu_time\": 295639.8985629747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate_reverse\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1043,\n            \"real_time\": 671254.0748197861,\n            \"cpu_time\": 671196.5484180269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate_reverse\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1356,\n            \"real_time\": 516030.6968759185,\n            \"cpu_time\": 516005.16224188753,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_lower_bound\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24293461.204345886,\n            \"cpu_time\": 24290931.034482714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_lower_bound\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 61653189.371678635,\n            \"cpu_time\": 61653181.818181746,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_lower_bound\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 57641239.58457882,\n            \"cpu_time\": 57637833.33333331,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_lower_bound\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 38295150.44344589,\n            \"cpu_time\": 38294222.22222236,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_index\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17833,\n            \"real_time\": 39254.75478558765,\n            \"cpu_time\": 39250.04205686071,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_index\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2954,\n            \"real_time\": 237289.22645850817,\n            \"cpu_time\": 237273.527420448,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_index\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1045,\n            \"real_time\": 667483.0545559882,\n            \"cpu_time\": 667419.1387559803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_index\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1401,\n            \"real_time\": 499907.56601044675,\n            \"cpu_time\": 499874.37544611125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_random\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1181,\n            \"real_time\": 592005.574148366,\n            \"cpu_time\": 591961.8966977121,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_random\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1109,\n            \"real_time\": 628493.8764702143,\n            \"cpu_time\": 628429.2155094678,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_random\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 540,\n            \"real_time\": 1280694.1369220752,\n            \"cpu_time\": 1280588.8888888927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_random\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 856,\n            \"real_time\": 818150.7488936796,\n            \"cpu_time\": 818094.6261682219,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74,\n            \"real_time\": 10624761.82375355,\n            \"cpu_time\": 9385081.081081046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 11115774.874471955,\n            \"cpu_time\": 9875930.555555554,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel\",\n            \"family_index\": 33,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 87730963.00299382,\n            \"cpu_time\": 82591000.00000036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel\",\n            \"family_index\": 34,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 68354545.45745796,\n            \"cpu_time\": 67578090.90909074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_reserve\",\n            \"family_index\": 35,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 10547246.835548196,\n            \"cpu_time\": 9399848.101265796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_reserve\",\n            \"family_index\": 36,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 87510212.99718155,\n            \"cpu_time\": 83862555.555556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_reserve\",\n            \"family_index\": 37,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 68953137.50719652,\n            \"cpu_time\": 67390999.99999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_clear\",\n            \"family_index\": 38,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 10716977.430598088,\n            \"cpu_time\": 9132458.333333304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_clear\",\n            \"family_index\": 39,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 11207459.514428463,\n            \"cpu_time\": 9731357.142857177,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_clear\",\n            \"family_index\": 40,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 88056013.89354302,\n            \"cpu_time\": 83354111.11111075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_clear\",\n            \"family_index\": 41,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 68515670.45404491,\n            \"cpu_time\": 66944363.63636346,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_10\",\n            \"family_index\": 42,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 434,\n            \"real_time\": 1948020.7374894537,\n            \"cpu_time\": 1651421.6589861815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_10\",\n            \"family_index\": 43,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 274,\n            \"real_time\": 2911470.346509676,\n            \"cpu_time\": 2570040.1459854334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_10\",\n            \"family_index\": 44,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 9460173.790821021,\n            \"cpu_time\": 9311947.368421102,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"family_index\": 45,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 6772294.874491097,\n            \"cpu_time\": 6688307.692307727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_100\",\n            \"family_index\": 46,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 892,\n            \"real_time\": 914227.1580535817,\n            \"cpu_time\": 774608.7443946169,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_100\",\n            \"family_index\": 47,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 430,\n            \"real_time\": 1872851.9370237926,\n            \"cpu_time\": 1637806.9767441822,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_100\",\n            \"family_index\": 48,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 381,\n            \"real_time\": 1857728.3462802845,\n            \"cpu_time\": 1834582.677165359,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"family_index\": 49,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1003,\n            \"real_time\": 705237.9522188487,\n            \"cpu_time\": 696478.5643070732,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_max\",\n            \"family_index\": 50,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2003,\n            \"real_time\": 420329.71342349506,\n            \"cpu_time\": 319559.6605092339,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_max\",\n            \"family_index\": 51,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1180,\n            \"real_time\": 695439.1593492385,\n            \"cpu_time\": 602417.7966101697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_max\",\n            \"family_index\": 52,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 696,\n            \"real_time\": 1028960.8476811956,\n            \"cpu_time\": 1026500.0000000005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"family_index\": 53,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11496,\n            \"real_time\": 65862.77835994957,\n            \"cpu_time\": 61107.08072372981,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_each_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:24:01-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/for_each_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.44629,\n            4.06006,\n            3.16357\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 3.7509016692638397e-10,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 4.169996827840805e-10,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 3.7497375160455705e-10,\n            \"cpu_time\": 9.999999999177334e-10,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12713991,\n            \"real_time\": 55.4285662143635,\n            \"cpu_time\": 55.420677897286566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3496322,\n            \"real_time\": 209.61013946923532,\n            \"cpu_time\": 209.05025338055253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1364550,\n            \"real_time\": 497.69985200673796,\n            \"cpu_time\": 486.1302260818583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 923998,\n            \"real_time\": 797.0115552080647,\n            \"cpu_time\": 734.996179645411,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 414870,\n            \"real_time\": 1681.6550966608227,\n            \"cpu_time\": 1572.244317497049,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 318498,\n            \"real_time\": 2194.8983982229347,\n            \"cpu_time\": 2091.881267700269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 164129,\n            \"real_time\": 4148.266248173059,\n            \"cpu_time\": 3597.456878430991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10593,\n            \"real_time\": 49261.80024954423,\n            \"cpu_time\": 49258.66138015665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28255,\n            \"real_time\": 26275.125356732882,\n            \"cpu_time\": 26267.563263139233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28760,\n            \"real_time\": 24247.138666426854,\n            \"cpu_time\": 24237.239221140535,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39558,\n            \"real_time\": 17623.938267413094,\n            \"cpu_time\": 17619.647100460057,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32604,\n            \"real_time\": 21452.541621925207,\n            \"cpu_time\": 21344.31358115562,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36492,\n            \"real_time\": 19786.268223890063,\n            \"cpu_time\": 19226.213964704555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23425,\n            \"real_time\": 27283.67128917349,\n            \"cpu_time\": 24848.665955176075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 6919777.227132259,\n            \"cpu_time\": 6919039.6039603865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 155,\n            \"real_time\": 4510779.574423307,\n            \"cpu_time\": 4510438.70967741,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 4024521.068045446,\n            \"cpu_time\": 4023562.500000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3582819.6610777806,\n            \"cpu_time\": 3582420.512820506,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3481717.9146921267,\n            \"cpu_time\": 3480970.0000000102,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 203,\n            \"real_time\": 3446394.502497255,\n            \"cpu_time\": 3434246.305418732,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 188,\n            \"real_time\": 3751593.9732250622,\n            \"cpu_time\": 3588765.957446826,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 400731,\n            \"real_time\": 1724.050130778557,\n            \"cpu_time\": 1724.0368227064996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 188005,\n            \"real_time\": 3744.823717605097,\n            \"cpu_time\": 3739.044174357083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154809,\n            \"real_time\": 4458.698299872223,\n            \"cpu_time\": 4442.338623723425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123876,\n            \"real_time\": 5686.056015611495,\n            \"cpu_time\": 5671.122735638859,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62259,\n            \"real_time\": 11357.86527222049,\n            \"cpu_time\": 11237.588139867325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52197,\n            \"real_time\": 13613.211335330809,\n            \"cpu_time\": 13167.557522462988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36178,\n            \"real_time\": 21813.72889580406,\n            \"cpu_time\": 20106.307700812606,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 403,\n            \"real_time\": 1743384.40930762,\n            \"cpu_time\": 1742583.1265508684,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 3713450.2687671734,\n            \"cpu_time\": 3711521.505376336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5034803.749294952,\n            \"cpu_time\": 5034409.999999952,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109,\n            \"real_time\": 5919903.669497767,\n            \"cpu_time\": 5914458.715596335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 12118319.915686497,\n            \"cpu_time\": 12107338.983050784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 16010042.577464549,\n            \"cpu_time\": 16005111.11111097,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 51859881.91321182,\n            \"cpu_time\": 46682416.66666617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 173638468.7537793,\n            \"cpu_time\": 173638500.00000092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 382169207.9654895,\n            \"cpu_time\": 378448499.9999975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 500838895.9686272,\n            \"cpu_time\": 500823499.9999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 637812250.0609607,\n            \"cpu_time\": 637549999.9999974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1427234707.9822793,\n            \"cpu_time\": 1426107999.9999921,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1651335333.9396417,\n            \"cpu_time\": 1651156000.0000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5021056332.974694,\n            \"cpu_time\": 3647441999.999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 281490,\n            \"real_time\": 2460.3825501094193,\n            \"cpu_time\": 2460.247255675155,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 208089,\n            \"real_time\": 3443.647309368769,\n            \"cpu_time\": 3442.724026738576,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 141536,\n            \"real_time\": 4992.919059544994,\n            \"cpu_time\": 4887.2442346823,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 116049,\n            \"real_time\": 6003.801196348504,\n            \"cpu_time\": 5850.744082241176,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 67624,\n            \"real_time\": 10456.12934644083,\n            \"cpu_time\": 10142.92263101844,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53265,\n            \"real_time\": 13214.687562046598,\n            \"cpu_time\": 12884.070214962796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26007,\n            \"real_time\": 26436.440189742774,\n            \"cpu_time\": 24027.838658822726,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 270,\n            \"real_time\": 2584803.2406496783,\n            \"cpu_time\": 2584625.9259259445,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 157,\n            \"real_time\": 4416677.815347293,\n            \"cpu_time\": 4415152.866242043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 121,\n            \"real_time\": 6871792.702350673,\n            \"cpu_time\": 6854595.041322245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 99,\n            \"real_time\": 7257237.797603011,\n            \"cpu_time\": 7256151.515151583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61,\n            \"real_time\": 11571150.278809985,\n            \"cpu_time\": 11568819.672131117,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17512853.126390837,\n            \"cpu_time\": 17486199.999999918,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 54945833.30582827,\n            \"cpu_time\": 53259599.99999981,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 820111,\n            \"real_time\": 852.899485639906,\n            \"cpu_time\": 852.5589828693934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 557607,\n            \"real_time\": 1260.7515992551105,\n            \"cpu_time\": 1256.7112679718812,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 387696,\n            \"real_time\": 1735.8688661636231,\n            \"cpu_time\": 1718.555259791179,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 327576,\n            \"real_time\": 2197.126010211535,\n            \"cpu_time\": 2105.636554570529,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180320,\n            \"real_time\": 3847.4478202412515,\n            \"cpu_time\": 3604.375554569645,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 129717,\n            \"real_time\": 5052.495694912164,\n            \"cpu_time\": 4437.082263697106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 137354,\n            \"real_time\": 6499.172459342831,\n            \"cpu_time\": 5611.805990360713,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 790370,\n            \"real_time\": 877.080617834821,\n            \"cpu_time\": 876.6172805141741,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 529021,\n            \"real_time\": 1333.3816144933303,\n            \"cpu_time\": 1331.0208857493376,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 395958,\n            \"real_time\": 1806.667626529415,\n            \"cpu_time\": 1793.2255441233701,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 303029,\n            \"real_time\": 2370.3171414366916,\n            \"cpu_time\": 2291.7047543303825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 177051,\n            \"real_time\": 3947.9827332155937,\n            \"cpu_time\": 3675.308244517118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 121894,\n            \"real_time\": 5488.374464619157,\n            \"cpu_time\": 5082.3994618275665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109375,\n            \"real_time\": 6589.241517441614,\n            \"cpu_time\": 5784.566857142766,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_latency_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:25:16-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/for_latency_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            7.06445,\n            4.81104,\n            3.52344\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 33923804.154619575,\n            \"cpu_time\": 20949.99999999736,\n            \"time_unit\": \"ns\",\n            \"mean\": 6.24917447566986e-08,\n            \"stddev\": 8.587150826082419e-08\n          },\n          {\n            \"name\": \"BM_tbb/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 48862776.785556756,\n            \"cpu_time\": 14858857.142857144,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.01490082878652694,\n            \"stddev\": 0.002949404112330031\n          },\n          {\n            \"name\": \"BM_tbb/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 35739713.55945104,\n            \"cpu_time\": 1290437.5000000051,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.001282141987758223,\n            \"stddev\": 0.000351309981794495\n          },\n          {\n            \"name\": \"BM_tbb/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 43657950.49670851,\n            \"cpu_time\": 8773749.999999996,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.010039383261755574,\n            \"stddev\": 0.0030713809355545326\n          },\n          {\n            \"name\": \"BM_tbb/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 42058494.74965362,\n            \"cpu_time\": 7397500.000000015,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.008642952001537196,\n            \"stddev\": 0.002124707657245938\n          },\n          {\n            \"name\": \"BM_tbb/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 40954658.87803584,\n            \"cpu_time\": 7849687.4999999795,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.008271031889307778,\n            \"stddev\": 0.0013236599199907661\n          },\n          {\n            \"name\": \"BM_tbb/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 42402966.129884586,\n            \"cpu_time\": 8393812.499999987,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.009023736798553728,\n            \"stddev\": 0.0015069593150374826\n          },\n          {\n            \"name\": \"BM_tbb/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 41874554.68490952,\n            \"cpu_time\": 8403687.500000007,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00922724212432513,\n            \"stddev\": 0.001227983250858294\n          },\n          {\n            \"name\": \"BM_dispenso/1/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 54589112.15492452,\n            \"cpu_time\": 20567846.153846152,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.020752502551588874,\n            \"stddev\": 0.0018596913951864178\n          },\n          {\n            \"name\": \"BM_dispenso/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 43784244.40510571,\n            \"cpu_time\": 10625266.666666662,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0111671816635256,\n            \"stddev\": 0.0030754829924476913\n          },\n          {\n            \"name\": \"BM_dispenso/3/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 43358578.46993296,\n            \"cpu_time\": 9496941.17647059,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.01034246281693306,\n            \"stddev\": 0.0012958759819160952\n          },\n          {\n            \"name\": \"BM_dispenso/4/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 42765568.58573766,\n            \"cpu_time\": 8872941.176470593,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.01026216076741762,\n            \"stddev\": 0.0035903512547681518\n          },\n          {\n            \"name\": \"BM_dispenso/6/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41872441.172873706,\n            \"cpu_time\": 7384764.70588236,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.009661495356875308,\n            \"stddev\": 0.002765153963870498\n          },\n          {\n            \"name\": \"BM_dispenso/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41280727.943076804,\n            \"cpu_time\": 8708823.529411767,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0099034447236644,\n            \"stddev\": 0.0017273019322917515\n          },\n          {\n            \"name\": \"BM_dispenso/12/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 42843593.75014901,\n            \"cpu_time\": 9419000.000000011,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.010476148192537948,\n            \"stddev\": 0.0019118203670036927\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"future_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:25:33-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/future_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.34229,\n            4.76855,\n            3.53076\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3180,\n            \"real_time\": 219139.01982541961,\n            \"cpu_time\": 218897.16981132078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 398,\n            \"real_time\": 1746741.9372347356,\n            \"cpu_time\": 1746562.814070351,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 14027711.65827289,\n            \"cpu_time\": 14027560.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 354523624.9919981,\n            \"cpu_time\": 30333.333333280403,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async hangs on this platform at this tree depth\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async hangs on this platform at this tree depth\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 170,\n            \"real_time\": 4020985.052920878,\n            \"cpu_time\": 10547.058823530326,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31890174.27344383,\n            \"cpu_time\": 14590.909090909805,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 254601930.6561599,\n            \"cpu_time\": 39000.00000012227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1009,\n            \"real_time\": 690767.3022359964,\n            \"cpu_time\": 124647.17542120913,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 150,\n            \"real_time\": 4652623.606380075,\n            \"cpu_time\": 718199.9999999977,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 34612708.300119266,\n            \"cpu_time\": 6023850.000000008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1170,\n            \"real_time\": 577466.0965300396,\n            \"cpu_time\": 518239.31623931724,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 156,\n            \"real_time\": 4399069.448341973,\n            \"cpu_time\": 3965262.8205128196,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 34593860.39758101,\n            \"cpu_time\": 33327399.99999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1215,\n            \"real_time\": 574602.0913438357,\n            \"cpu_time\": 408180.24691358017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4764640.664731796,\n            \"cpu_time\": 2959523.4899328914,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33979803.573207125,\n            \"cpu_time\": 24248047.61904763,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1016,\n            \"real_time\": 678018.4960766424,\n            \"cpu_time\": 120951.77165354372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 147,\n            \"real_time\": 4746979.870675068,\n            \"cpu_time\": 546680.27210885,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 36242789.472453296,\n            \"cpu_time\": 1249105.2631578948,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:25:55-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/graph_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            8.41797,\n            5.39355,\n            3.79199\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_taskflow_build_big_tree\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_build_big_tree\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 243,\n            \"real_time\": 2875657.4077010457,\n            \"cpu_time\": 2875485.5967078195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 851,\n            \"real_time\": 827747.3067011156,\n            \"cpu_time\": 827685.0763807284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 807,\n            \"real_time\": 862210.0879697884,\n            \"cpu_time\": 862167.286245353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_chain\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_chain\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12263,\n            \"real_time\": 60791.02103590594,\n            \"cpu_time\": 58967.62619261194,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_group\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_group\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1308093,\n            \"real_time\": 541.1421435173419,\n            \"cpu_time\": 540.8919702192431,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73532,\n            \"real_time\": 9584.254691533728,\n            \"cpu_time\": 9579.62519719306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66108,\n            \"real_time\": 10396.300373474847,\n            \"cpu_time\": 10395.685847401233,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195459,\n            \"real_time\": 3659.363984078001,\n            \"cpu_time\": 3659.15614016239,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 191322,\n            \"real_time\": 3698.6554966538197,\n            \"cpu_time\": 3698.3357899248385,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 701,\n            \"real_time\": 951695.781049668,\n            \"cpu_time\": 951616.2624822138,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 704,\n            \"real_time\": 990644.596558096,\n            \"cpu_time\": 990267.0454545687,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_scene_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:26:06-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/graph_scene_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            8.14502,\n            5.43018,\n            3.82324\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74,\n            \"real_time\": 8991288.89432177,\n            \"cpu_time\": 8593310.810810804,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 118,\n            \"real_time\": 6132357.387795602,\n            \"cpu_time\": 5699567.796610213,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_taskflow/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 117,\n            \"real_time\": 5869669.512383895,\n            \"cpu_time\": 30717.948717945754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3363,\n            \"real_time\": 211265.1030637419,\n            \"cpu_time\": 178140.9455842942,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"idle_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:26:11-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/idle_pool_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            7.65283,\n            5.37305,\n            3.8125\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34811,\n            \"real_time\": 19.876605094076083,\n            \"cpu_time\": 19.8752980379765,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.6915899999999999,\n            \"\\t1 System\": 0.0003010000000000009\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31183,\n            \"real_time\": 21.382990475001293,\n            \"cpu_time\": 21.381618189398065,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3257750000000001,\n            \"\\t1 System\": 0.007456000000000001\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31283,\n            \"real_time\": 22.286794489143066,\n            \"cpu_time\": 22.26317808394335,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.0631470000000007,\n            \"\\t1 System\": 0.024092999999999996\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30977,\n            \"real_time\": 22.525470509770873,\n            \"cpu_time\": 22.523840268586387,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.756743,\n            \"\\t1 System\": 0.03369499999999999\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25307,\n            \"real_time\": 27.53688208799312,\n            \"cpu_time\": 27.376931283834494,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.9313660000000006,\n            \"\\t1 System\": 0.11682800000000002\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23640,\n            \"real_time\": 30.76591581644336,\n            \"cpu_time\": 30.744077834179368,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 5.565076999999999,\n            \"\\t1 System\": 0.23336\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22614,\n            \"real_time\": 31.450521047075117,\n            \"cpu_time\": 30.187184929689543,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.151220000000002,\n            \"\\t1 System\": 2.6798740000000003\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3536,\n            \"real_time\": 202.49054977371108,\n            \"cpu_time\": 202.36283936651537,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.7151320000000005,\n            \"\\t1 System\": 0.00044100000000035777\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3319,\n            \"real_time\": 211.45170473564627,\n            \"cpu_time\": 211.37119614341688,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3817029999999981,\n            \"\\t1 System\": 0.020817000000000085\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3176,\n            \"real_time\": 218.94605381951504,\n            \"cpu_time\": 218.3063602015114,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.041240000000002,\n            \"\\t1 System\": 0.03802299999999992\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3143,\n            \"real_time\": 223.13469074011047,\n            \"cpu_time\": 223.02036271078592,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.7607169999999996,\n            \"\\t1 System\": 0.04319600000000001\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2507,\n            \"real_time\": 266.5956322427677,\n            \"cpu_time\": 259.36338252891966,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.673504000000001,\n            \"\\t1 System\": 0.19490100000000066\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2245,\n            \"real_time\": 291.8967149035802,\n            \"cpu_time\": 285.72917594654734,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.657289000000006,\n            \"\\t1 System\": 0.44586399999999937\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2324,\n            \"real_time\": 307.4214535463992,\n            \"cpu_time\": 256.581755593804,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.153966000000004,\n            \"\\t1 System\": 2.3588839999999998\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 20110.643383197705,\n            \"cpu_time\": 20108.588235294133,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.6832999999999956,\n            \"\\t1 System\": 0.00041000000000046555\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 21075.44572826362,\n            \"cpu_time\": 21044.515151515145,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3734490000000008,\n            \"\\t1 System\": 0.015882000000001284\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21924.488279182697,\n            \"cpu_time\": 21842.656250000036,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.0555909999999997,\n            \"\\t1 System\": 0.039666999999999675\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 22010.22312886292,\n            \"cpu_time\": 21993.93548387099,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.68248100000001,\n            \"\\t1 System\": 0.04473600000000033\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26,\n            \"real_time\": 27368.96795865435,\n            \"cpu_time\": 27349.076923076864,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.162501000000006,\n            \"\\t1 System\": 0.09997000000000078\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 28985.84850217131,\n            \"cpu_time\": 28703.590909090857,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.704695999999998,\n            \"\\t1 System\": 0.33609000000000044\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 27960.51908323231,\n            \"cpu_time\": 21166.249999999978,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 4.458363000000006,\n            \"\\t1 System\": 1.6796430000000004\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 104556.84515181929,\n            \"cpu_time\": 47.71428571410346,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.00020100000000411455,\n            \"\\t1 System\": 0.0001610000000002998\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 104071.60714800868,\n            \"cpu_time\": 57.28571428572796,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.002512999999993326,\n            \"\\t1 System\": 0.000700000000000145\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 104046.22029247029,\n            \"cpu_time\": 54.42857142869327,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.004127000000011094,\n            \"\\t1 System\": 0.0010929999999991225\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102836.98800152967,\n            \"cpu_time\": 66.57142857185201,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.006748000000001753,\n            \"\\t1 System\": 0.005035000000001233\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 104953.79771704653,\n            \"cpu_time\": 64.4285714283147,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.010867999999987887,\n            \"\\t1 System\": 0.019202999999999193\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 104008.9107118547,\n            \"cpu_time\": 62.999999999797346,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.015360999999998626,\n            \"\\t1 System\": 0.032249999999999446\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 103789.22613537205,\n            \"cpu_time\": 57.57142857122842,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0262429999999938,\n            \"\\t1 System\": 0.06250200000000028\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 260148,\n            \"real_time\": 2.6099716967115327,\n            \"cpu_time\": 2.6089149253501844,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.1533160000000038,\n            \"\\t1 System\": 0.19860800000000012\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 263839,\n            \"real_time\": 2.876337148986388,\n            \"cpu_time\": 2.854790231921745,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.2549109999999928,\n            \"\\t1 System\": 0.23581300000000027\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 153884,\n            \"real_time\": 4.577939389659891,\n            \"cpu_time\": 4.482070910555981,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3382270000000034,\n            \"\\t1 System\": 0.5144420000000007\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112524,\n            \"real_time\": 6.169086150290484,\n            \"cpu_time\": 5.495423198606512,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.3762290000000093,\n            \"\\t1 System\": 0.8164660000000019\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20602,\n            \"real_time\": 33.59804067846777,\n            \"cpu_time\": 29.75643141442579,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.0157329999999973,\n            \"\\t1 System\": 1.1087130000000016\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5476,\n            \"real_time\": 120.55436597638365,\n            \"cpu_time\": 105.71146822498193,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.810654999999997,\n            \"\\t1 System\": 1.3284559999999992\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7106,\n            \"real_time\": 99.13712003313648,\n            \"cpu_time\": 70.1355192794827,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.0601170000000053,\n            \"\\t1 System\": 3.660781\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68160,\n            \"real_time\": 10.086900307693051,\n            \"cpu_time\": 10.080399061032837,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.162080000000003,\n            \"\\t1 System\": 0.20879199999999898\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73794,\n            \"real_time\": 9.700433531144588,\n            \"cpu_time\": 9.694243434425518,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.2136150000000043,\n            \"\\t1 System\": 0.21590999999999738\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30944,\n            \"real_time\": 19.14006889841207,\n            \"cpu_time\": 16.939859100310166,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.9157560000000018,\n            \"\\t1 System\": 0.31224500000000077\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31100,\n            \"real_time\": 23.499718650882027,\n            \"cpu_time\": 19.493022508038457,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.1045599999999922,\n            \"\\t1 System\": 0.5644500000000008\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15112,\n            \"real_time\": 47.57320341472196,\n            \"cpu_time\": 43.25046320804671,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.799869000000001,\n            \"\\t1 System\": 0.9667640000000013\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1221,\n            \"real_time\": 541.0529615320906,\n            \"cpu_time\": 474.58476658476536,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.858187000000001,\n            \"\\t1 System\": 1.3863130000000012\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2201,\n            \"real_time\": 456.7189913485089,\n            \"cpu_time\": 307.7010449795519,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 3.172341000000003,\n            \"\\t1 System\": 5.233697000000003\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 809,\n            \"real_time\": 784.5392460475488,\n            \"cpu_time\": 784.0284301606827,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.0710940000000022,\n            \"\\t1 System\": 0.1968570000000014\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 921,\n            \"real_time\": 767.9795059623211,\n            \"cpu_time\": 764.0553745928297,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.1941690000000023,\n            \"\\t1 System\": 0.2163579999999996\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 893,\n            \"real_time\": 781.1575677727682,\n            \"cpu_time\": 770.5419932810825,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.1697070000000025,\n            \"\\t1 System\": 0.22031500000000648\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 853,\n            \"real_time\": 794.2233294421088,\n            \"cpu_time\": 782.0902696365812,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.1354939999999942,\n            \"\\t1 System\": 0.21906800000000004\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 777,\n            \"real_time\": 924.4239060244159,\n            \"cpu_time\": 898.4993564993514,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.2408520000000038,\n            \"\\t1 System\": 0.3254620000000017\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 9090.774577672188,\n            \"cpu_time\": 8351.012820512802,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 2.418918000000005,\n            \"\\t1 System\": 2.3314730000000026\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5547.0087507274,\n            \"cpu_time\": 3658.550000000105,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 1.2764270000000124,\n            \"\\t1 System\": 4.151496000000002\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 103949.43443991776,\n            \"cpu_time\": 33.57142857294905,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.00010199999999827014,\n            \"\\t1 System\": 0.00014600000000086766\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102323.14886525273,\n            \"cpu_time\": 35.14285714244027,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.003084000000001197,\n            \"\\t1 System\": 0.009870999999996855\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102151.94643075977,\n            \"cpu_time\": 30.571428570372714,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.0059219999999982065,\n            \"\\t1 System\": 0.018789999999995644\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 101760.25587134063,\n            \"cpu_time\": 34.571428570424295,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.010214999999988095,\n            \"\\t1 System\": 0.034114999999999895\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 101917.30356642178,\n            \"cpu_time\": 29.14285714337796,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.01927899999998317,\n            \"\\t1 System\": 0.09242600000000323\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102839.75000493228,\n            \"cpu_time\": 35.14285714345533,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.02798700000002441,\n            \"\\t1 System\": 0.15623599999999982\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 101509.90472175181,\n            \"cpu_time\": 33.14285714241448,\n            \"time_unit\": \"us\",\n            \"\\t0 User\": 0.05967300000000364,\n            \"\\t1 System\": 0.3277100000000033\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"locality_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:27:03-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/locality_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            8.47461,\n            5.87061,\n            4.08057\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2821,\n            \"real_time\": 247876.72809881443,\n            \"cpu_time\": 247864.9415101027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10068703.57086882,\n            \"cpu_time\": 10067757.142857144,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 80385893.55742766,\n            \"cpu_time\": 80373444.4444444,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1568,\n            \"real_time\": 445868.729002541,\n            \"cpu_time\": 445842.4744897962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3357,\n            \"real_time\": 205472.97945906932,\n            \"cpu_time\": 205398.86803693787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4018,\n            \"real_time\": 173522.08809559952,\n            \"cpu_time\": 172416.87406669997,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4036,\n            \"real_time\": 173656.44600198994,\n            \"cpu_time\": 172548.81070366694,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4023,\n            \"real_time\": 173070.272941234,\n            \"cpu_time\": 172186.42803877709,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 15213417.587801814,\n            \"cpu_time\": 15212282.608695637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 170,\n            \"real_time\": 4108408.823445001,\n            \"cpu_time\": 4107805.882352946,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 285,\n            \"real_time\": 2564908.771595934,\n            \"cpu_time\": 2486119.2982456074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 274,\n            \"real_time\": 2547032.087633427,\n            \"cpu_time\": 2485773.7226277343,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 276,\n            \"real_time\": 2570804.0435953685,\n            \"cpu_time\": 2505634.0579710184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 120765617.99040063,\n            \"cpu_time\": 120737000.0000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33021849.24195033,\n            \"cpu_time\": 33017999.99999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 23729265.7959564,\n            \"cpu_time\": 22879758.620689657,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 23557516.66861276,\n            \"cpu_time\": 22843166.666666668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 23197238.90007784,\n            \"cpu_time\": 22457666.666666515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2730,\n            \"real_time\": 256090.7359074651,\n            \"cpu_time\": 256080.5860805866,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5107,\n            \"real_time\": 133841.48384591582,\n            \"cpu_time\": 132877.81476404925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6666,\n            \"real_time\": 110695.41330053339,\n            \"cpu_time\": 107643.71437143696,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3921,\n            \"real_time\": 162321.85666438678,\n            \"cpu_time\": 136821.21907676623,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2502,\n            \"real_time\": 287738.9424298849,\n            \"cpu_time\": 244803.35731414816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10075088.700146547,\n            \"cpu_time\": 10074228.571428584,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 156,\n            \"real_time\": 4509631.679423201,\n            \"cpu_time\": 4499006.410256402,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 266,\n            \"real_time\": 2717709.7443036065,\n            \"cpu_time\": 2465454.887218058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 252,\n            \"real_time\": 2859782.0796892936,\n            \"cpu_time\": 2123468.2539682547,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 255,\n            \"real_time\": 2831912.5803297055,\n            \"cpu_time\": 2403674.5098039303,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 80980611.11134787,\n            \"cpu_time\": 80974000.00000042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 36509410.049276136,\n            \"cpu_time\": 36472526.31578948,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 26487858.03898203,\n            \"cpu_time\": 24531777.77777769,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24607481.310497325,\n            \"cpu_time\": 8468931.034482587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 28115873.483733997,\n            \"cpu_time\": 11614518.518518515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2650,\n            \"real_time\": 260737.31134979508,\n            \"cpu_time\": 260725.28301886946,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5660,\n            \"real_time\": 126822.4602494415,\n            \"cpu_time\": 126817.8445229688,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2963,\n            \"real_time\": 233759.12656686342,\n            \"cpu_time\": 226565.98042524222,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 798,\n            \"real_time\": 890183.0614990272,\n            \"cpu_time\": 869269.4235588984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 399,\n            \"real_time\": 1744616.6465763834,\n            \"cpu_time\": 1615571.4285714277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 10334427.074720973,\n            \"cpu_time\": 10333426.470588194,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4752867.173828535,\n            \"cpu_time\": 4752684.563758365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 251,\n            \"real_time\": 2846860.394078451,\n            \"cpu_time\": 2787199.203187227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3673726.0665410226,\n            \"cpu_time\": 3568743.5897436067,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 141,\n            \"real_time\": 4649647.163121519,\n            \"cpu_time\": 3323007.092198541,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 87189692.75651035,\n            \"cpu_time\": 86646499.99999963,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 38419599.56076203,\n            \"cpu_time\": 38335833.333333604,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 23323620.832525194,\n            \"cpu_time\": 16615833.333333304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24227678.173639137,\n            \"cpu_time\": 15181999.999999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 25613959.82463312,\n            \"cpu_time\": 14204357.142857203,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:27:51-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/nested_for_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            7.60645,\n            6.12695,\n            4.28174\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 315661,\n            \"real_time\": 2229.308628670427,\n            \"cpu_time\": 2228.919632137008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 5908019.538861658,\n            \"cpu_time\": 5907752.212389381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 564495479.0477641,\n            \"cpu_time\": 564444500.0000005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45742,\n            \"real_time\": 14961.287396672922,\n            \"cpu_time\": 14959.11853438853,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58224,\n            \"real_time\": 12207.42807181078,\n            \"cpu_time\": 12206.358202802976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58388,\n            \"real_time\": 12109.488096784127,\n            \"cpu_time\": 12107.487839967118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60500,\n            \"real_time\": 11760.601240849077,\n            \"cpu_time\": 11758.87603305787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54189,\n            \"real_time\": 11638.886580109067,\n            \"cpu_time\": 11634.206204211172,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49948,\n            \"real_time\": 14006.300714716304,\n            \"cpu_time\": 13965.90454072238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59331,\n            \"real_time\": 12124.174831781393,\n            \"cpu_time\": 12037.198092059794,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 8783293.869591465,\n            \"cpu_time\": 8782671.052631564,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 162,\n            \"real_time\": 4241980.457057555,\n            \"cpu_time\": 4240753.086419762,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 235,\n            \"real_time\": 2869621.8084425055,\n            \"cpu_time\": 2869570.2127659624,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 314,\n            \"real_time\": 2134516.5890350845,\n            \"cpu_time\": 2133245.222929935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 463,\n            \"real_time\": 1444861.9526096864,\n            \"cpu_time\": 1444755.9395248424,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 597,\n            \"real_time\": 1110844.1524429114,\n            \"cpu_time\": 1110051.9262981608,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 706,\n            \"real_time\": 1001690.9234882687,\n            \"cpu_time\": 962287.5354107652,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 453164749.9534302,\n            \"cpu_time\": 453134000.00000036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 243543985.998258,\n            \"cpu_time\": 243529666.66666612,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 161323500.01134908,\n            \"cpu_time\": 160891500.00000086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 112321208.39413257,\n            \"cpu_time\": 112302599.9999996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 71781819.45346296,\n            \"cpu_time\": 71781777.77777803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 50853854.17138847,\n            \"cpu_time\": 50781500.00000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 43659128.00754554,\n            \"cpu_time\": 41191785.7142858,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 283499,\n            \"real_time\": 2479.9473156576137,\n            \"cpu_time\": 2479.758306025776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 407262,\n            \"real_time\": 1714.804801569383,\n            \"cpu_time\": 1712.3547004139914,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 472442,\n            \"real_time\": 1468.1176928052757,\n            \"cpu_time\": 1467.3822395129953,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 540041,\n            \"real_time\": 1326.2928186469464,\n            \"cpu_time\": 1325.212344988618,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 239769,\n            \"real_time\": 2478.049009819242,\n            \"cpu_time\": 2468.02547451924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 250396,\n            \"real_time\": 2678.877158411769,\n            \"cpu_time\": 2669.667247080581,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115889,\n            \"real_time\": 4652.9743209281805,\n            \"cpu_time\": 4159.126405439686,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 5935303.946898784,\n            \"cpu_time\": 5934946.428571461,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 227,\n            \"real_time\": 3007479.995645025,\n            \"cpu_time\": 3007330.396475751,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 316,\n            \"real_time\": 2061836.6300057666,\n            \"cpu_time\": 2061661.3924050664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 408,\n            \"real_time\": 1524610.7034138679,\n            \"cpu_time\": 1524321.0784313786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 592,\n            \"real_time\": 1016174.1976500363,\n            \"cpu_time\": 1015342.905405422,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 816,\n            \"real_time\": 776653.9522837027,\n            \"cpu_time\": 771006.1274509768,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 709,\n            \"real_time\": 841270.4513078536,\n            \"cpu_time\": 813963.328631868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 583668707.9863622,\n            \"cpu_time\": 583620000.0000033,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 294945667.0321524,\n            \"cpu_time\": 294883499.99999744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 212272416.6838452,\n            \"cpu_time\": 212058000.00000134,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 188557124.98771027,\n            \"cpu_time\": 188509999.99999908,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 113317701.34468873,\n            \"cpu_time\": 113211333.33333342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 80586281.241267,\n            \"cpu_time\": 78373125.0000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 64663950.00461489,\n            \"cpu_time\": 62068599.99999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 284109,\n            \"real_time\": 2462.673509170537,\n            \"cpu_time\": 2462.2627231097913,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 409303,\n            \"real_time\": 1721.2704694947508,\n            \"cpu_time\": 1719.6795528007417,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 451649,\n            \"real_time\": 1556.5033178025333,\n            \"cpu_time\": 1555.4534605412664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 523509,\n            \"real_time\": 1325.0999505581974,\n            \"cpu_time\": 1324.5560248247818,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 257513,\n            \"real_time\": 3050.0764350750364,\n            \"cpu_time\": 2862.7525600649183,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 245922,\n            \"real_time\": 2881.858373892265,\n            \"cpu_time\": 2865.7338505704965,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100000,\n            \"real_time\": 5503.386249765754,\n            \"cpu_time\": 5073.849999999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 113,\n            \"real_time\": 5954529.86756521,\n            \"cpu_time\": 5951867.256637184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 231,\n            \"real_time\": 2944964.46749139,\n            \"cpu_time\": 2944670.995670969,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 335,\n            \"real_time\": 1975472.8868798313,\n            \"cpu_time\": 1974420.8955223255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 442,\n            \"real_time\": 1476109.4455881154,\n            \"cpu_time\": 1475504.5248868566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 655,\n            \"real_time\": 988000.4443569493,\n            \"cpu_time\": 987865.6488549435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 863,\n            \"real_time\": 769253.235271466,\n            \"cpu_time\": 759950.1738122725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1002,\n            \"real_time\": 638253.1187164332,\n            \"cpu_time\": 623100.798403208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 553281709.0861499,\n            \"cpu_time\": 553260999.999992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 288024207.984563,\n            \"cpu_time\": 287993999.9999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 179009603.9767377,\n            \"cpu_time\": 178983249.99999815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 138357441.59296155,\n            \"cpu_time\": 138338400.00000066,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 86717338.49041629,\n            \"cpu_time\": 86623000.00000122,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 61907262.5064291,\n            \"cpu_time\": 61857499.99999927,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 48208218.74697382,\n            \"cpu_time\": 47145916.66666597,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:29:14-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/nested_pool_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            7.03613,\n            6.20459,\n            4.46875\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1028,\n            \"real_time\": 677.9331226057667,\n            \"cpu_time\": 677.8531128404667,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1295,\n            \"real_time\": 542.970623957662,\n            \"cpu_time\": 542.9559845559845,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1199,\n            \"real_time\": 587.9234428400231,\n            \"cpu_time\": 587.2452043369475,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1282,\n            \"real_time\": 555.4199165536756,\n            \"cpu_time\": 555.3510140405615,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1180,\n            \"real_time\": 587.1199152306101,\n            \"cpu_time\": 587.0601694915248,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1259,\n            \"real_time\": 563.036702108008,\n            \"cpu_time\": 561.6036536934075,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1252,\n            \"real_time\": 577.751663792432,\n            \"cpu_time\": 570.4448881789134,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 21761.02016106128,\n            \"cpu_time\": 21758.7741935484,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 17681.982731673776,\n            \"cpu_time\": 17681.317073170736,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 15489.978723208162,\n            \"cpu_time\": 15489.255319148937,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 12552.85566107237,\n            \"cpu_time\": 12551.392857142828,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 11108.409728022349,\n            \"cpu_time\": 11107.378787878779,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10250.611914255258,\n            \"cpu_time\": 10246.157142857142,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 9308.678650113783,\n            \"cpu_time\": 9081.318181818167,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3296486.375038512,\n            \"cpu_time\": 3296262.0000000005,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2090060.2079927921,\n            \"cpu_time\": 2089933.0000000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1534770.958009176,\n            \"cpu_time\": 1534744.9999999974,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1185793.9169276506,\n            \"cpu_time\": 1185774.000000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 867856.0410626233,\n            \"cpu_time\": 867816.9999999987,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 734020.6250082701,\n            \"cpu_time\": 730373.0000000001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 778120.04100997,\n            \"cpu_time\": 748463.0000000009,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108,\n            \"real_time\": 6308.988814621612,\n            \"cpu_time\": 23.16666666666465,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6073.80393713746,\n            \"cpu_time\": 19.098214285743047,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 124,\n            \"real_time\": 5519.547379545627,\n            \"cpu_time\": 18.088709677419313,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131,\n            \"real_time\": 5577.856549488395,\n            \"cpu_time\": 18.78625954198678,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 68,\n            \"real_time\": 10230.621324701453,\n            \"cpu_time\": 29.02941176466226,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 15092.790765846346,\n            \"cpu_time\": 30.021276595764665,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 26041.050924471132,\n            \"cpu_time\": 28.703703703867077,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 228647.87497868142,\n            \"cpu_time\": 469.6666666674787,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 199361.65264031538,\n            \"cpu_time\": 423.00000000021026,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 176662.8750192467,\n            \"cpu_time\": 418.9999999999472,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 179852.5414778851,\n            \"cpu_time\": 396.250000000542,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 333325.68750483915,\n            \"cpu_time\": 558.5000000003504,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 512416.7500762269,\n            \"cpu_time\": 562.9999999960944,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 881811.0000574961,\n            \"cpu_time\": 677.9999999970698,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_folly/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_folly/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_folly/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_folly/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_folly/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_folly/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"We run out of memory here with too many elements\",\n            \"iterations\": 1,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2946,\n            \"real_time\": 237.19465645511926,\n            \"cpu_time\": 237.17956551256015,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4642,\n            \"real_time\": 151.14610276406873,\n            \"cpu_time\": 151.1314088754846,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4182,\n            \"real_time\": 157.7835167379135,\n            \"cpu_time\": 157.772118603539,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4872,\n            \"real_time\": 142.0926124703182,\n            \"cpu_time\": 142.08394909687973,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2379,\n            \"real_time\": 308.4210979784735,\n            \"cpu_time\": 308.2702816309369,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1802,\n            \"real_time\": 401.3422819099427,\n            \"cpu_time\": 401.29245283019077,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1159,\n            \"real_time\": 565.7262010323052,\n            \"cpu_time\": 563.767903364968,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 7160.414123137919,\n            \"cpu_time\": 7159.673469387778,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 319,\n            \"real_time\": 2193.1773761789486,\n            \"cpu_time\": 2193.103448275863,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 279,\n            \"real_time\": 2517.0265841314495,\n            \"cpu_time\": 2516.960573476723,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 281,\n            \"real_time\": 2530.2844020137,\n            \"cpu_time\": 2530.2704626334685,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 161,\n            \"real_time\": 4163.695912900734,\n            \"cpu_time\": 4161.645962732935,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 175,\n            \"real_time\": 4653.025000090046,\n            \"cpu_time\": 4650.46285714286,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 157,\n            \"real_time\": 4338.411623938306,\n            \"cpu_time\": 4300.312101910812,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1148256.374988705,\n            \"cpu_time\": 1148195.0000000012,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 187597.614742117,\n            \"cpu_time\": 187582.7500000007,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 196777.96875475906,\n            \"cpu_time\": 196772.74999999916,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 209864.9999825284,\n            \"cpu_time\": 209837.66666666765,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 281596.97198619443,\n            \"cpu_time\": 281591.33333333133,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 356942.9999915883,\n            \"cpu_time\": 356914.50000000204,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 444069.0830233507,\n            \"cpu_time\": 440850.4999999963,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10023,\n            \"real_time\": 69.99702763920337,\n            \"cpu_time\": 69.99151950513784,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5715,\n            \"real_time\": 121.31665213227481,\n            \"cpu_time\": 121.31093613298454,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6434,\n            \"real_time\": 109.35908843443853,\n            \"cpu_time\": 109.35265775567309,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6477,\n            \"real_time\": 108.74788342634731,\n            \"cpu_time\": 108.74170140497075,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3989,\n            \"real_time\": 175.95745601048554,\n            \"cpu_time\": 175.94835798445584,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4946,\n            \"real_time\": 145.60373717097258,\n            \"cpu_time\": 145.21977355438764,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3850,\n            \"real_time\": 185.18111481053103,\n            \"cpu_time\": 179.47974025974105,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370,\n            \"real_time\": 1895.4101352121781,\n            \"cpu_time\": 1895.3027027027024,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 400,\n            \"real_time\": 1733.7116674752906,\n            \"cpu_time\": 1730.1424999999958,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 489,\n            \"real_time\": 1413.0601574664893,\n            \"cpu_time\": 1413.0020449897936,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 573,\n            \"real_time\": 1257.5391203369848,\n            \"cpu_time\": 1257.4520069808036,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 389,\n            \"real_time\": 1902.5739074677497,\n            \"cpu_time\": 1902.5655526992189,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 398,\n            \"real_time\": 1790.606889443182,\n            \"cpu_time\": 1790.5276381909478,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 399,\n            \"real_time\": 1817.8500427063882,\n            \"cpu_time\": 1806.2932330826925,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 292041.08350677416,\n            \"cpu_time\": 292020.0000000008,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 130980.92500586063,\n            \"cpu_time\": 130921.60000000063,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 111263.52084102109,\n            \"cpu_time\": 111255.66666666487,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100296.16670882596,\n            \"cpu_time\": 100286.71428571353,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 103861.78570999099,\n            \"cpu_time\": 103856.2857142864,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 82522.8843346445,\n            \"cpu_time\": 82511.33333333232,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 85837.98962354194,\n            \"cpu_time\": 84001.24999999914,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"once_function_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:30:28-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/once_function_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            7.44824,\n            6.52588,\n            4.73535\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_move_std_function<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29159984,\n            \"real_time\": 24.158670975557346,\n            \"cpu_time\": 24.154334241061314,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kSmallSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 133832976,\n            \"real_time\": 5.204623791909096,\n            \"cpu_time\": 5.202342657313395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kMediumSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28263872,\n            \"real_time\": 24.550034826692528,\n            \"cpu_time\": 24.539595990245072,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kMediumSize>\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100822423,\n            \"real_time\": 6.812845839092673,\n            \"cpu_time\": 6.812442902706269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kLargeSize>\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27128103,\n            \"real_time\": 24.582920522600364,\n            \"cpu_time\": 24.580819381288848,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kLargeSize>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94187298,\n            \"real_time\": 7.438441518400829,\n            \"cpu_time\": 7.437828824859161,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15766547,\n            \"real_time\": 44.21355443294617,\n            \"cpu_time\": 44.21056810980873,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25323691,\n            \"real_time\": 27.811982148424182,\n            \"cpu_time\": 27.808702925651758,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1117640,\n            \"real_time\": 627.0593616821525,\n            \"cpu_time\": 627.0140653519911,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kSmallSize>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 257965,\n            \"real_time\": 2734.0989397390713,\n            \"cpu_time\": 2733.9522803481077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kSmallSize>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 500529,\n            \"real_time\": 1398.8958840787318,\n            \"cpu_time\": 1398.7481244842943,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 622244,\n            \"real_time\": 1124.6337175150072,\n            \"cpu_time\": 1124.5009996078684,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kMediumSize>\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 237325,\n            \"real_time\": 2964.939429110469,\n            \"cpu_time\": 2964.613926050771,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kMediumSize>\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 445494,\n            \"real_time\": 1539.047102661202,\n            \"cpu_time\": 1538.411291734571,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 386328,\n            \"real_time\": 1817.4631815245443,\n            \"cpu_time\": 1817.300325112339,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kLargeSize>\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212673,\n            \"real_time\": 3246.7841850951504,\n            \"cpu_time\": 3246.5193042840533,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kLargeSize>\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370835,\n            \"real_time\": 1890.5727399449413,\n            \"cpu_time\": 1890.118246659571,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92501,\n            \"real_time\": 7571.629852905779,\n            \"cpu_time\": 7571.291121177055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70075,\n            \"real_time\": 10034.847177918622,\n            \"cpu_time\": 10034.220478059206,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70283,\n            \"real_time\": 10222.249092835804,\n            \"cpu_time\": 10153.066886729386,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pipeline_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:30:47-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/pipeline_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            5.75977,\n            6.19922,\n            4.65918\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 114005916.67431097,\n            \"cpu_time\": 113784333.33333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 60666458.33197981,\n            \"cpu_time\": 13889000.000000022,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 105327486.00235207,\n            \"cpu_time\": 93244333.33333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100358023.85703261,\n            \"cpu_time\": 17142.857142842568,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_par/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 13244808.961215585,\n            \"cpu_time\": 91547.16981131386,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_par/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 18570681.720221832,\n            \"cpu_time\": 18184888.88888889,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow_par/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100174589.2821678,\n            \"cpu_time\": 17428.57142866023,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pool_allocator_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:30:54-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/pool_allocator_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.33936,\n            6.31201,\n            4.70801\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2356,\n            \"real_time\": 297837.8959717182,\n            \"cpu_time\": 297824.7028862479,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 520,\n            \"real_time\": 1393100.5615561914,\n            \"cpu_time\": 1393005.76923077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19876,\n            \"real_time\": 35381.84665267378,\n            \"cpu_time\": 35378.949486818274,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4838,\n            \"real_time\": 144298.9355109866,\n            \"cpu_time\": 144289.16907813158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21631,\n            \"real_time\": 32329.23618875474,\n            \"cpu_time\": 32326.66081087326,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5280,\n            \"real_time\": 133055.0820002276,\n            \"cpu_time\": 133047.15909090906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2241,\n            \"real_time\": 312082.44089198427,\n            \"cpu_time\": 312065.5957161986,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 552,\n            \"real_time\": 1286931.7644694145,\n            \"cpu_time\": 1286865.9420289889,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19848,\n            \"real_time\": 35833.98831308906,\n            \"cpu_time\": 35831.36839983868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4842,\n            \"real_time\": 144236.78231143608,\n            \"cpu_time\": 144227.59190417174,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21665,\n            \"real_time\": 32361.86439259558,\n            \"cpu_time\": 32348.811447034383,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5285,\n            \"real_time\": 132326.7975434407,\n            \"cpu_time\": 132322.23273415354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 3967560.369346757,\n            \"cpu_time\": 3967323.863636367,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 15925258.522408761,\n            \"cpu_time\": 15924363.636363614,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17940,\n            \"real_time\": 35744.06120115258,\n            \"cpu_time\": 35742.14046822741,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4767,\n            \"real_time\": 146309.707341323,\n            \"cpu_time\": 146232.43129851043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21497,\n            \"real_time\": 32453.493513815025,\n            \"cpu_time\": 32447.829929757707,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5251,\n            \"real_time\": 133103.29765478693,\n            \"cpu_time\": 133091.22071986325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33396,\n            \"real_time\": 21265.480894466433,\n            \"cpu_time\": 21263.92382321245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8200,\n            \"real_time\": 86182.02232244628,\n            \"cpu_time\": 85796.46341463391,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33213,\n            \"real_time\": 21064.785143470246,\n            \"cpu_time\": 21050.55249450521,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8287,\n            \"real_time\": 84566.9069640627,\n            \"cpu_time\": 84562.44720646809,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33444,\n            \"real_time\": 21059.53734711275,\n            \"cpu_time\": 21037.555316349786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8180,\n            \"real_time\": 85263.86002597825,\n            \"cpu_time\": 85244.37652811747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33056,\n            \"real_time\": 21147.46064142755,\n            \"cpu_time\": 21146.02492739597,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8167,\n            \"real_time\": 85567.00244149553,\n            \"cpu_time\": 85494.79613076992,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33165,\n            \"real_time\": 21021.85662787536,\n            \"cpu_time\": 21007.990351274002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8069,\n            \"real_time\": 86704.20746064727,\n            \"cpu_time\": 86542.19853761289,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33469,\n            \"real_time\": 21179.439691280913,\n            \"cpu_time\": 21146.10535122043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8248,\n            \"real_time\": 84837.98606465747,\n            \"cpu_time\": 84820.19883608156,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 552,\n            \"real_time\": 1257238.148684627,\n            \"cpu_time\": 1257005.4347826105,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 116,\n            \"real_time\": 5947916.66411891,\n            \"cpu_time\": 5939586.206896573,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3578,\n            \"real_time\": 191077.9184113632,\n            \"cpu_time\": 189247.06539966396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 645,\n            \"real_time\": 1017347.9984911489,\n            \"cpu_time\": 1015550.3875968937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 563,\n            \"real_time\": 1016821.344399603,\n            \"cpu_time\": 1016788.6323268178,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 359,\n            \"real_time\": 1979630.9191059102,\n            \"cpu_time\": 1979392.7576601515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3658,\n            \"real_time\": 193045.1749578554,\n            \"cpu_time\": 191059.32203389838,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 635,\n            \"real_time\": 1071525.3937138817,\n            \"cpu_time\": 1068973.2283464575,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 17206997.976910956,\n            \"cpu_time\": 17203731.707317133,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 69498659.09039296,\n            \"cpu_time\": 69488272.72727245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3755,\n            \"real_time\": 191963.53768421395,\n            \"cpu_time\": 189964.0479360856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 692,\n            \"real_time\": 1022619.2788928854,\n            \"cpu_time\": 1018784.682080926,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 189,\n            \"real_time\": 3733305.555581061,\n            \"cpu_time\": 3715592.592592592,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 15166702.127936196,\n            \"cpu_time\": 15127255.319148868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 21899995.53541254,\n            \"cpu_time\": 21748500.00000004,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 94885845.79667076,\n            \"cpu_time\": 94108399.99999964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 189,\n            \"real_time\": 3693569.2224355917,\n            \"cpu_time\": 3686539.6825396856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 15767791.676586743,\n            \"cpu_time\": 15711972.972973078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 17763089.136375736,\n            \"cpu_time\": 17554666.66666668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 110689090.91409296,\n            \"cpu_time\": 110072545.45454517,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 98668744.8748853,\n            \"cpu_time\": 96294874.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 387625041.53419286,\n            \"cpu_time\": 380588000.00000304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 25595886.67936623,\n            \"cpu_time\": 25404639.99999986,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 73615657.45021734,\n            \"cpu_time\": 72802444.44444388,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 8368770.837058457,\n            \"cpu_time\": 7197375.000000028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 34217269.91402228,\n            \"cpu_time\": 25368260.869565144,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 13813426.250126215,\n            \"cpu_time\": 12982530.000000026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 98524399.99813214,\n            \"cpu_time\": 91578100.00000027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90,\n            \"real_time\": 9259785.644503104,\n            \"cpu_time\": 7735211.111111085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 40081666.66608304,\n            \"cpu_time\": 34279888.888889335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 16729679.932309823,\n            \"cpu_time\": 15998954.545454454,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 111432819.50110881,\n            \"cpu_time\": 106378833.33333361,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 218771116.80805683,\n            \"cpu_time\": 155988200.00000018,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 844508291.920647,\n            \"cpu_time\": 547278999.9999961,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 6825904.255396033,\n            \"cpu_time\": 6037446.808510734,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 68130451.39036451,\n            \"cpu_time\": 63474833.33333336,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"rw_lock_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:32:00-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/rw_lock_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.03369,\n            6.0498,\n            4.71484\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2433,\n            \"real_time\": 285183.70649920136,\n            \"cpu_time\": 285143.4443074394,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2439,\n            \"real_time\": 286609.3173463474,\n            \"cpu_time\": 286583.84583845834,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2367,\n            \"real_time\": 291821.08153557987,\n            \"cpu_time\": 291746.9370511193,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1987,\n            \"real_time\": 333605.1836488914,\n            \"cpu_time\": 333556.61801711126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2289,\n            \"real_time\": 304676.5871115709,\n            \"cpu_time\": 304628.65880297095,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 10781069.015138201,\n            \"cpu_time\": 10778625.000000013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 66,\n            \"real_time\": 10617996.84998043,\n            \"cpu_time\": 10614757.57575757,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10062712.499140095,\n            \"cpu_time\": 10054342.857142868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 71,\n            \"real_time\": 9875637.323359473,\n            \"cpu_time\": 9872225.352112692,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 9892706.59596918,\n            \"cpu_time\": 9891500.000000017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 206,\n            \"real_time\": 3389171.1167050796,\n            \"cpu_time\": 3388742.7184466114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 207,\n            \"real_time\": 3393791.261093088,\n            \"cpu_time\": 3387946.8599033887,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212,\n            \"real_time\": 3316036.556772712,\n            \"cpu_time\": 3315665.094339622,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 210,\n            \"real_time\": 3430593.8475188753,\n            \"cpu_time\": 3426319.047619053,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 211,\n            \"real_time\": 3324420.814804062,\n            \"cpu_time\": 3323838.862559244,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65,\n            \"real_time\": 10857366.030820861,\n            \"cpu_time\": 10836446.15384615,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 48073186.1355404,\n            \"cpu_time\": 32678199.999999907,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 223555250.01573065,\n            \"cpu_time\": 123011000.00000058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 868961500.0039339,\n            \"cpu_time\": 424693999.9999988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 65,\n            \"real_time\": 10633065.384955935,\n            \"cpu_time\": 10621769.230769254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 48234949.354082346,\n            \"cpu_time\": 33167999.999999862,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 211338639.02650774,\n            \"cpu_time\": 112529000.00000091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 945047250.0175238,\n            \"cpu_time\": 451454999.9999993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 69,\n            \"real_time\": 10262880.435523886,\n            \"cpu_time\": 10247072.463768069,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 51817922.64504891,\n            \"cpu_time\": 37626357.142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 210097471.98938084,\n            \"cpu_time\": 115275999.99999912,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 902531540.9526229,\n            \"cpu_time\": 425050999.9999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10063079.757882016,\n            \"cpu_time\": 10060485.714285707,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 64839170.908089735,\n            \"cpu_time\": 52157100.00000016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 201540541.5149871,\n            \"cpu_time\": 116553999.99999982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 769367125.0017359,\n            \"cpu_time\": 388481999.99999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 10008825.586243933,\n            \"cpu_time\": 10002971.42857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 107829791.57686765,\n            \"cpu_time\": 97136714.28571402,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 187002697.9886461,\n            \"cpu_time\": 118212499.99999939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 527345874.9288693,\n            \"cpu_time\": 312021999.9999989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 3584332.2789863814,\n            \"cpu_time\": 3581928.9340101467,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 29757812.502793968,\n            \"cpu_time\": 29736636.363636456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 153225666.7560432,\n            \"cpu_time\": 153049750.0000001,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1005173167.0973823,\n            \"cpu_time\": 1004213000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 198,\n            \"real_time\": 3549493.4747494156,\n            \"cpu_time\": 3547525.2525252188,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 25392336.44320457,\n            \"cpu_time\": 25371259.259259205,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 129610604.16031007,\n            \"cpu_time\": 129506500.00000034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 681908959.0571821,\n            \"cpu_time\": 681435999.999998,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 199,\n            \"real_time\": 3500579.1455591517,\n            \"cpu_time\": 3498834.1708542528,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 19340842.104467906,\n            \"cpu_time\": 19313736.84210526,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 93561865.77739815,\n            \"cpu_time\": 93421777.7777775,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 421600875.0372566,\n            \"cpu_time\": 421406000.0000011,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3494274.7902823617,\n            \"cpu_time\": 3491900.0000000014,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 18518503.631323416,\n            \"cpu_time\": 18468217.391304404,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 80677546.32793367,\n            \"cpu_time\": 80408777.77777824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 303473750.01292676,\n            \"cpu_time\": 302208499.999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 199,\n            \"real_time\": 3497630.653168126,\n            \"cpu_time\": 3496311.557788975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 15670082.399932045,\n            \"cpu_time\": 15651911.111111064,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 72606312.49907117,\n            \"cpu_time\": 72521833.33333306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 345658187.5216216,\n            \"cpu_time\": 345167499.99999875,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:32:53-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/simple_for_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            5.40771,\n            5.80957,\n            4.70264\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 3.7497375160455705e-10,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 3.33995558321476e-10,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000000000000,\n            \"real_time\": 4.159519448876381e-10,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87913,\n            \"real_time\": 8165.779896374998,\n            \"cpu_time\": 8153.458532867718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86321,\n            \"real_time\": 8037.026042295156,\n            \"cpu_time\": 8026.0770843711225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 86218,\n            \"real_time\": 8037.461237201799,\n            \"cpu_time\": 8025.818274606237,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84666,\n            \"real_time\": 8240.657407288209,\n            \"cpu_time\": 8225.580516382017,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83979,\n            \"real_time\": 8341.751115465577,\n            \"cpu_time\": 8328.117743721641,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84502,\n            \"real_time\": 8312.600589860573,\n            \"cpu_time\": 8297.992946912495,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110625,\n            \"real_time\": 6706.632388555734,\n            \"cpu_time\": 6690.350282485884,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6960,\n            \"real_time\": 100227.72385754847,\n            \"cpu_time\": 100207.90229885063,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11654,\n            \"real_time\": 59484.88355694319,\n            \"cpu_time\": 59474.85841771054,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12657,\n            \"real_time\": 52727.867978380484,\n            \"cpu_time\": 52707.67164414962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16345,\n            \"real_time\": 43392.40593667623,\n            \"cpu_time\": 43369.53196696231,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20370,\n            \"real_time\": 34315.32071344646,\n            \"cpu_time\": 34303.681885125225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22358,\n            \"real_time\": 31916.541818011847,\n            \"cpu_time\": 31848.42114679306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23912,\n            \"real_time\": 29117.38528583078,\n            \"cpu_time\": 28830.29441284716,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 95,\n            \"real_time\": 7338198.684891196,\n            \"cpu_time\": 7337063.157894749,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 4650172.735070994,\n            \"cpu_time\": 4649152.317880792,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 3990181.3467043787,\n            \"cpu_time\": 3989914.7727272646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 193,\n            \"real_time\": 3615828.155578534,\n            \"cpu_time\": 3614886.0103627034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 199,\n            \"real_time\": 3496726.758979336,\n            \"cpu_time\": 3496502.5125628086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3519768.33480876,\n            \"cpu_time\": 3421474.999999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3609583.9740039827,\n            \"cpu_time\": 3455071.7948717824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 353843.63749762997,\n            \"cpu_time\": 24622.4999999999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_taskflow/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4077,\n            \"real_time\": 611494.5324984838,\n            \"cpu_time\": 13285.504047094599,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_taskflow/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4679,\n            \"real_time\": 676986.7403423571,\n            \"cpu_time\": 15305.407138277471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_taskflow/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2782,\n            \"real_time\": 652553.273910907,\n            \"cpu_time\": 14242.271746946417,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_taskflow/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2542,\n            \"real_time\": 673465.8076437403,\n            \"cpu_time\": 15416.601101496424,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_taskflow/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2658,\n            \"real_time\": 669435.7599653136,\n            \"cpu_time\": 18573.363431153026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_taskflow/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2028,\n            \"real_time\": 640626.19177924,\n            \"cpu_time\": 17914.20118343172,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_taskflow/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 278,\n            \"real_time\": 6618754.4964528605,\n            \"cpu_time\": 5417.266187047191,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_taskflow/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 456,\n            \"real_time\": 7100949.651334974,\n            \"cpu_time\": 6157.894736838038,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_taskflow/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 697,\n            \"real_time\": 6924421.50928823,\n            \"cpu_time\": 7484.935437587161,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_taskflow/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 827,\n            \"real_time\": 6658505.492121828,\n            \"cpu_time\": 8733.978234582537,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_taskflow/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 852,\n            \"real_time\": 6728089.886210299,\n            \"cpu_time\": 7775.821596243732,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_taskflow/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 825,\n            \"real_time\": 6686934.74677363,\n            \"cpu_time\": 36729.69696969999,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_taskflow/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 723,\n            \"real_time\": 6173689.661123745,\n            \"cpu_time\": 14164.59197787083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_taskflow/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 65613551.46935539,\n            \"cpu_time\": 10705.882352870249,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_taskflow/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 62734740.45696535,\n            \"cpu_time\": 10228.571428630825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_taskflow/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 55741849.60810605,\n            \"cpu_time\": 10926.829268260286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_taskflow/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 66204095.930727415,\n            \"cpu_time\": 11162.790697582306,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_taskflow/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 66936078.59249988,\n            \"cpu_time\": 11136.3636364265,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_taskflow/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 67894904.34245883,\n            \"cpu_time\": 14318.181818124225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_taskflow/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 68204006.95072576,\n            \"cpu_time\": 17666.66666672531,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14779640,\n            \"real_time\": 46.04082318406511,\n            \"cpu_time\": 46.02710214863133,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15128295,\n            \"real_time\": 46.121137047132294,\n            \"cpu_time\": 46.11114471260628,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15380987,\n            \"real_time\": 45.6716139252072,\n            \"cpu_time\": 45.62490040463591,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15415975,\n            \"real_time\": 45.31050043920065,\n            \"cpu_time\": 45.30547046164773,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15453771,\n            \"real_time\": 45.043442278045454,\n            \"cpu_time\": 45.030821279802915,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15519117,\n            \"real_time\": 44.65237938838554,\n            \"cpu_time\": 44.631791873210304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15560843,\n            \"real_time\": 45.36657069061462,\n            \"cpu_time\": 45.323765556917536,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11170,\n            \"real_time\": 53254.1927425466,\n            \"cpu_time\": 53247.53804834396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27962,\n            \"real_time\": 29055.281845266134,\n            \"cpu_time\": 29042.200128746397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28081,\n            \"real_time\": 25434.214130765933,\n            \"cpu_time\": 25407.464121647885,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33266,\n            \"real_time\": 20753.614803694283,\n            \"cpu_time\": 20725.4854806711,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32264,\n            \"real_time\": 21763.29528190336,\n            \"cpu_time\": 21584.273493677025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35056,\n            \"real_time\": 19784.576820456372,\n            \"cpu_time\": 19485.451848471188,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22857,\n            \"real_time\": 30466.086278966693,\n            \"cpu_time\": 27775.911099444216,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 6973216.671030968,\n            \"cpu_time\": 6971770.000000034,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 4434089.062851854,\n            \"cpu_time\": 4429068.749999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 177,\n            \"real_time\": 4035585.920331673,\n            \"cpu_time\": 4030988.7005649637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3537435.68695604,\n            \"cpu_time\": 3536692.307692281,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 198,\n            \"real_time\": 3492578.0762363262,\n            \"cpu_time\": 3490898.98989899,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3488039.7899542004,\n            \"cpu_time\": 3462500.0000000126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 3816219.086142918,\n            \"cpu_time\": 3563424.731182783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15423891,\n            \"real_time\": 45.09730502006492,\n            \"cpu_time\": 45.08602919976511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13882313,\n            \"real_time\": 45.64059318042956,\n            \"cpu_time\": 45.63223722156411,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15478352,\n            \"real_time\": 45.256922898416505,\n            \"cpu_time\": 45.252815028369675,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15634535,\n            \"real_time\": 44.84328820778732,\n            \"cpu_time\": 44.83523174817794,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15729300,\n            \"real_time\": 44.616578037289734,\n            \"cpu_time\": 44.60134907465701,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15534249,\n            \"real_time\": 45.360166752215584,\n            \"cpu_time\": 45.33672660969984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15393870,\n            \"real_time\": 44.85081562246261,\n            \"cpu_time\": 44.814396899545514,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10560,\n            \"real_time\": 62958.91335784373,\n            \"cpu_time\": 62951.32575757578,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28092,\n            \"real_time\": 30042.53285602966,\n            \"cpu_time\": 30031.85960415796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27048,\n            \"real_time\": 25885.285711607594,\n            \"cpu_time\": 25784.863945577952,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31950,\n            \"real_time\": 21132.81558624852,\n            \"cpu_time\": 21103.129890453805,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32391,\n            \"real_time\": 21684.45583664198,\n            \"cpu_time\": 21556.481738754417,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35875,\n            \"real_time\": 20245.767724197296,\n            \"cpu_time\": 19851.01045296175,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24873,\n            \"real_time\": 28018.36996152383,\n            \"cpu_time\": 27022.031922164395,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 99,\n            \"real_time\": 6956598.071165082,\n            \"cpu_time\": 6955929.292929221,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 155,\n            \"real_time\": 4425629.03232512,\n            \"cpu_time\": 4425245.161290364,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 4020051.6139686275,\n            \"cpu_time\": 4018971.590909036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 194,\n            \"real_time\": 3562241.8346843617,\n            \"cpu_time\": 3561979.381443293,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3488446.670235134,\n            \"cpu_time\": 3486479.999999972,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 201,\n            \"real_time\": 3477888.0595984813,\n            \"cpu_time\": 3458920.3980099745,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187,\n            \"real_time\": 3805045.903794826,\n            \"cpu_time\": 3674941.17647065,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15709081,\n            \"real_time\": 44.987582849126134,\n            \"cpu_time\": 44.976978602375674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15553284,\n            \"real_time\": 45.241509251644985,\n            \"cpu_time\": 45.228647531930086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15568701,\n            \"real_time\": 45.06578615484587,\n            \"cpu_time\": 44.95525991539128,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15369991,\n            \"real_time\": 44.85204585067788,\n            \"cpu_time\": 44.833272836660406,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15535354,\n            \"real_time\": 45.74117956453297,\n            \"cpu_time\": 45.436428419976906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15472608,\n            \"real_time\": 45.04289128142026,\n            \"cpu_time\": 45.0277031512715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15668480,\n            \"real_time\": 45.413671780799255,\n            \"cpu_time\": 45.365153480108646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10554,\n            \"real_time\": 51190.11351296539,\n            \"cpu_time\": 51183.43755921748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23155,\n            \"real_time\": 29825.089961697395,\n            \"cpu_time\": 29809.8466853811,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32657,\n            \"real_time\": 21817.611842727216,\n            \"cpu_time\": 21791.652631901456,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35774,\n            \"real_time\": 19956.242662196415,\n            \"cpu_time\": 19931.06725554915,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39144,\n            \"real_time\": 17250.3182854661,\n            \"cpu_time\": 17233.318005314166,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39775,\n            \"real_time\": 17438.931487229056,\n            \"cpu_time\": 17272.130735386552,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30973,\n            \"real_time\": 22678.690566877525,\n            \"cpu_time\": 20921.835146740526,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 6992323.019790768,\n            \"cpu_time\": 6991128.712871251,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154,\n            \"real_time\": 4473483.227737635,\n            \"cpu_time\": 4472623.376623458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 3990414.062917063,\n            \"cpu_time\": 3988676.1363636064,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 194,\n            \"real_time\": 3610045.9641527343,\n            \"cpu_time\": 3606979.3814432924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 200,\n            \"real_time\": 3525103.9551803838,\n            \"cpu_time\": 3522005.0000000214,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 201,\n            \"real_time\": 3511311.3583644754,\n            \"cpu_time\": 3461935.323383062,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3595507.6923784916,\n            \"cpu_time\": 3098923.0769231073,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:35:34-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/simple_pool_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.68408,\n            6.21191,\n            5.04932\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34927,\n            \"real_time\": 19.8398803228476,\n            \"cpu_time\": 19.838291293268814,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32641,\n            \"real_time\": 21.453196654229036,\n            \"cpu_time\": 21.450905303146346,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31004,\n            \"real_time\": 22.69957908730194,\n            \"cpu_time\": 22.693362146819748,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28977,\n            \"real_time\": 23.50722269228718,\n            \"cpu_time\": 23.50022431583669,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24532,\n            \"real_time\": 28.096659465626274,\n            \"cpu_time\": 28.090330996249786,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22485,\n            \"real_time\": 30.80636348632513,\n            \"cpu_time\": 30.795908383366704,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18943,\n            \"real_time\": 35.63749802625345,\n            \"cpu_time\": 35.59679037111335,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3528,\n            \"real_time\": 198.3208854826877,\n            \"cpu_time\": 198.27494331065776,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3340,\n            \"real_time\": 214.01594311394868,\n            \"cpu_time\": 213.9799401197606,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3142,\n            \"real_time\": 225.85424600509342,\n            \"cpu_time\": 225.76607256524528,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2933,\n            \"real_time\": 236.0107824733456,\n            \"cpu_time\": 235.94374360722833,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2616,\n            \"real_time\": 271.23990176574523,\n            \"cpu_time\": 268.81460244648343,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2325,\n            \"real_time\": 302.4201432583473,\n            \"cpu_time\": 302.2795698924731,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1902,\n            \"real_time\": 350.3743648728832,\n            \"cpu_time\": 349.3275499474242,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 118496.85420747846,\n            \"cpu_time\": 118483.1000000001,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 71578.05089890544,\n            \"cpu_time\": 71564.55555555515,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 48723.08976840801,\n            \"cpu_time\": 48704.99999999987,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 34684.518500903825,\n            \"cpu_time\": 34674.88888888879,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31769.51890451495,\n            \"cpu_time\": 31761.090909090974,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 38521.57458344376,\n            \"cpu_time\": 38509.63157894757,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 39328.79821054245,\n            \"cpu_time\": 39274.894736842136,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4692,\n            \"real_time\": 148.68277557375256,\n            \"cpu_time\": 99.80051150895093,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_folly/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4452,\n            \"real_time\": 170.54736633995935,\n            \"cpu_time\": 142.02291105121307,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_folly/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3841,\n            \"real_time\": 182.11511766673323,\n            \"cpu_time\": 173.8208799791715,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_folly/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2680,\n            \"real_time\": 261.15918846509015,\n            \"cpu_time\": 244.00634328358174,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_folly/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2272,\n            \"real_time\": 307.15302201430643,\n            \"cpu_time\": 287.3644366197173,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_folly/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2279,\n            \"real_time\": 335.81870731240946,\n            \"cpu_time\": 300.99648968845923,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_folly/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2250,\n            \"real_time\": 311.4121848613852,\n            \"cpu_time\": 294.1626666666666,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_folly/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 456,\n            \"real_time\": 1534.4369516752888,\n            \"cpu_time\": 1019.6118421052589,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_folly/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 473,\n            \"real_time\": 1571.235376169972,\n            \"cpu_time\": 1365.3911205073998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_folly/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 396,\n            \"real_time\": 1884.3878383955193,\n            \"cpu_time\": 1862.72727272727,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_folly/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 261,\n            \"real_time\": 2626.10696147328,\n            \"cpu_time\": 2563.134099616855,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_folly/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 227,\n            \"real_time\": 3088.5960000037885,\n            \"cpu_time\": 3004.581497797344,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_folly/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 208,\n            \"real_time\": 3101.0480765521957,\n            \"cpu_time\": 3015.6153846153584,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_folly/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 230,\n            \"real_time\": 3003.0686610742755,\n            \"cpu_time\": 2924.6043478261,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/1/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_folly/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 159814.14599809796,\n            \"cpu_time\": 106667.9999999991,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/2/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_folly/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 170841.8227499351,\n            \"cpu_time\": 147650.24999999988,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/3/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_folly/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 188804.3542567175,\n            \"cpu_time\": 187568.7500000005,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/4/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_folly/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 263194.27764974535,\n            \"cpu_time\": 258315.66666666817,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/6/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_folly/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 296969.9170207605,\n            \"cpu_time\": 289315.9999999995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/8/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_folly/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 281913.70848799124,\n            \"cpu_time\": 275637.500000002,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_folly/12/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_folly/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 284064.2704977654,\n            \"cpu_time\": 279716.999999998,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104015,\n            \"real_time\": 6.6472640090395885,\n            \"cpu_time\": 6.646849012161651,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 53.13554169842973,\n            \"cpu_time\": 53.11850000000007,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5524,\n            \"real_time\": 115.53375434739398,\n            \"cpu_time\": 115.48117306299766,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4766,\n            \"real_time\": 176.5114003512969,\n            \"cpu_time\": 176.3197650020977,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1915,\n            \"real_time\": 336.5354872048485,\n            \"cpu_time\": 336.19060052219714,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1939,\n            \"real_time\": 366.3849066597106,\n            \"cpu_time\": 366.1000515729758,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1927,\n            \"real_time\": 367.56199222496895,\n            \"cpu_time\": 366.91074208614407,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10454,\n            \"real_time\": 65.35277969934586,\n            \"cpu_time\": 65.34207002104486,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 945,\n            \"real_time\": 791.3980158735757,\n            \"cpu_time\": 790.947089947089,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 678,\n            \"real_time\": 1056.4191873696327,\n            \"cpu_time\": 1056.1253687315668,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 498,\n            \"real_time\": 1480.8765901477043,\n            \"cpu_time\": 1480.3192771084416,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 216,\n            \"real_time\": 3175.5945183923122,\n            \"cpu_time\": 3174.2685185184923,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 201,\n            \"real_time\": 3376.355930463184,\n            \"cpu_time\": 3374.601990049779,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 196,\n            \"real_time\": 4013.4710867946246,\n            \"cpu_time\": 4011.474489795908,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109,\n            \"real_time\": 6503.729743524155,\n            \"cpu_time\": 6502.495412844067,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 64677.60609335859,\n            \"cpu_time\": 64671.363636363625,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 101286.94788727444,\n            \"cpu_time\": 101254.3749999999,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 136104.68339174986,\n            \"cpu_time\": 136063.59999999995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 316134.353983216,\n            \"cpu_time\": 316006.999999999,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 353628.5205045715,\n            \"cpu_time\": 353498.50000000413,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 384219.5204924792,\n            \"cpu_time\": 384050.50000000076,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 928366,\n            \"real_time\": 0.7554262456378871,\n            \"cpu_time\": 0.7553206386274381,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19374,\n            \"real_time\": 36.13760710292121,\n            \"cpu_time\": 36.12945184267588,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9767,\n            \"real_time\": 74.59056004233452,\n            \"cpu_time\": 74.56076584416967,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8378,\n            \"real_time\": 83.86936523736156,\n            \"cpu_time\": 83.83623776557543,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4707,\n            \"real_time\": 149.81741747684936,\n            \"cpu_time\": 149.73932441045352,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5398,\n            \"real_time\": 125.04704669342217,\n            \"cpu_time\": 124.97925157465758,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4703,\n            \"real_time\": 149.13546308786368,\n            \"cpu_time\": 146.60301934934932,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97360,\n            \"real_time\": 7.199973038284088,\n            \"cpu_time\": 7.199301561216111,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1952,\n            \"real_time\": 355.62803120720656,\n            \"cpu_time\": 355.5804303278664,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 833,\n            \"real_time\": 766.3786014103714,\n            \"cpu_time\": 766.2160864345659,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 875,\n            \"real_time\": 849.6708571910858,\n            \"cpu_time\": 849.3131428571456,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 460,\n            \"real_time\": 1335.4970106814542,\n            \"cpu_time\": 1335.1391304348185,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 520,\n            \"real_time\": 1266.95488848222,\n            \"cpu_time\": 1265.174999999985,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 454,\n            \"real_time\": 1527.3928964851088,\n            \"cpu_time\": 1521.1343612334842,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 978,\n            \"real_time\": 718.8960889369584,\n            \"cpu_time\": 718.7351738241438,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 35827.11874623783,\n            \"cpu_time\": 35821.899999999834,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 82232.31011329012,\n            \"cpu_time\": 82213.77777777641,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 88812.23437492736,\n            \"cpu_time\": 88794.62500000023,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 139060.3750187438,\n            \"cpu_time\": 139031.0000000028,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 134771.74999813238,\n            \"cpu_time\": 134729.16666666634,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 153261.50821056217,\n            \"cpu_time\": 152815.19999999774,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"small_buffer_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:36:54-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/small_buffer_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.86816,\n            6.26025,\n            5.16309\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5587,\n            \"real_time\": 125303.26364931643,\n            \"cpu_time\": 125290.49579380703,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1386,\n            \"real_time\": 508444.8953462875,\n            \"cpu_time\": 508370.1298701297,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13142,\n            \"real_time\": 53302.40831650446,\n            \"cpu_time\": 53296.75848424895,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3269,\n            \"real_time\": 214782.18355085887,\n            \"cpu_time\": 214758.64178647884,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5672,\n            \"real_time\": 124989.33357486768,\n            \"cpu_time\": 124974.25952045145,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1368,\n            \"real_time\": 505341.70981474785,\n            \"cpu_time\": 505266.08187134494,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11123,\n            \"real_time\": 60749.228267215316,\n            \"cpu_time\": 60741.886181785514,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2888,\n            \"real_time\": 244387.94149076848,\n            \"cpu_time\": 244348.33795013843,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4984,\n            \"real_time\": 138000.96970177098,\n            \"cpu_time\": 137987.76083467118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1235,\n            \"real_time\": 573576.0461350502,\n            \"cpu_time\": 573497.1659919026,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12392,\n            \"real_time\": 57018.46957966995,\n            \"cpu_time\": 57010.409941897924,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3112,\n            \"real_time\": 225975.01609099738,\n            \"cpu_time\": 225858.29048843245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2720,\n            \"real_time\": 314926.0268187123,\n            \"cpu_time\": 254273.1617647058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 816,\n            \"real_time\": 1201311.3235155412,\n            \"cpu_time\": 944523.284313727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 7568,\n            \"real_time\": 120258.6493397035,\n            \"cpu_time\": 92525.23784355166,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1792,\n            \"real_time\": 444873.3035522829,\n            \"cpu_time\": 360395.089285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 2000,\n            \"real_time\": 429508.1455493346,\n            \"cpu_time\": 346153.0000000006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 480,\n            \"real_time\": 3098163.281538291,\n            \"cpu_time\": 2277033.3333333307,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 5824,\n            \"real_time\": 162576.32181965004,\n            \"cpu_time\": 127333.61950549482,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1424,\n            \"real_time\": 678291.8443492603,\n            \"cpu_time\": 503144.6629213481,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 752,\n            \"real_time\": 1934699.7973154932,\n            \"cpu_time\": 1476522.6063829765,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 112,\n            \"real_time\": 7334677.465093722,\n            \"cpu_time\": 5811178.571428568,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 4432,\n            \"real_time\": 190252.0963226593,\n            \"cpu_time\": 146544.90072202164,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1088,\n            \"real_time\": 757798.5616080696,\n            \"cpu_time\": 576999.0808823525,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"summing_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:37:06-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/summing_for_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            6.01074,\n            6.09961,\n            5.125\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11338236,\n            \"real_time\": 61.868015977933,\n            \"cpu_time\": 61.86147474792375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11237,\n            \"real_time\": 62131.92283685184,\n            \"cpu_time\": 62126.27925602919,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6271191.964125527,\n            \"cpu_time\": 6270714.285714288,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87489,\n            \"real_time\": 8098.8852890526505,\n            \"cpu_time\": 8084.433471636433,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88696,\n            \"real_time\": 7902.885981032539,\n            \"cpu_time\": 7890.896996482366,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88433,\n            \"real_time\": 7910.169754879776,\n            \"cpu_time\": 7897.459093324887,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88271,\n            \"real_time\": 7924.401366363232,\n            \"cpu_time\": 7913.788220366828,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83537,\n            \"real_time\": 8467.075966689852,\n            \"cpu_time\": 8455.34314136251,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 77020,\n            \"real_time\": 9021.862826939605,\n            \"cpu_time\": 8965.853025188273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93833,\n            \"real_time\": 7333.295140880929,\n            \"cpu_time\": 7299.862521714123,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9462,\n            \"real_time\": 73253.95878199255,\n            \"cpu_time\": 73133.16423589093,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12311,\n            \"real_time\": 44695.539841018835,\n            \"cpu_time\": 44671.43205263578,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18471,\n            \"real_time\": 37628.8799210418,\n            \"cpu_time\": 37616.64230415248,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20871,\n            \"real_time\": 32160.988931691067,\n            \"cpu_time\": 32142.92559053238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26772,\n            \"real_time\": 25780.759752318532,\n            \"cpu_time\": 25766.808606006325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28639,\n            \"real_time\": 24416.323301077882,\n            \"cpu_time\": 24377.806487656784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32829,\n            \"real_time\": 21390.852327258417,\n            \"cpu_time\": 21131.530049651195,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111,\n            \"real_time\": 6311540.910344874,\n            \"cpu_time\": 6310936.936936938,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 215,\n            \"real_time\": 3253811.628146227,\n            \"cpu_time\": 3252986.046511642,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 313,\n            \"real_time\": 2251415.4695676635,\n            \"cpu_time\": 2250999.9999999893,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388,\n            \"real_time\": 1787936.53366924,\n            \"cpu_time\": 1787626.288659791,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 420,\n            \"real_time\": 1652575.4951761058,\n            \"cpu_time\": 1652040.4761904792,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 422,\n            \"real_time\": 1658270.8342896854,\n            \"cpu_time\": 1656618.4834123254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 434,\n            \"real_time\": 1616450.6518942937,\n            \"cpu_time\": 1576617.5115207308,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9590946,\n            \"real_time\": 73.21236872374634,\n            \"cpu_time\": 73.20456188576136,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9402331,\n            \"real_time\": 73.83848047515738,\n            \"cpu_time\": 73.83456293976444,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9235539,\n            \"real_time\": 75.63617836556358,\n            \"cpu_time\": 75.63077801956086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9242022,\n            \"real_time\": 75.48505532789856,\n            \"cpu_time\": 75.4760159627407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9152934,\n            \"real_time\": 76.54764035438431,\n            \"cpu_time\": 76.53054200980816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9244072,\n            \"real_time\": 75.94152857903019,\n            \"cpu_time\": 75.9144887664227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9126467,\n            \"real_time\": 76.52603958821783,\n            \"cpu_time\": 76.44184765035587,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11263,\n            \"real_time\": 62124.53013849104,\n            \"cpu_time\": 62118.88484418008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21559,\n            \"real_time\": 32542.895864285958,\n            \"cpu_time\": 32172.410594183475,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31233,\n            \"real_time\": 23049.065345463572,\n            \"cpu_time\": 23029.39198924209,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38345,\n            \"real_time\": 18169.309326149654,\n            \"cpu_time\": 18139.653149041555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39209,\n            \"real_time\": 18001.76831836735,\n            \"cpu_time\": 17822.99982146956,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41244,\n            \"real_time\": 17093.629762444518,\n            \"cpu_time\": 16671.467364950084,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39385,\n            \"real_time\": 19147.251492042946,\n            \"cpu_time\": 17790.783293131943,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6243269.7231997745,\n            \"cpu_time\": 6242482.14285718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 220,\n            \"real_time\": 3192353.977250274,\n            \"cpu_time\": 3191795.4545454374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321,\n            \"real_time\": 2180611.7600537953,\n            \"cpu_time\": 2180442.3676012265,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 390,\n            \"real_time\": 1783559.7206169788,\n            \"cpu_time\": 1783471.7948717983,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 418,\n            \"real_time\": 1660651.514533925,\n            \"cpu_time\": 1654722.4880382582,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 422,\n            \"real_time\": 1646918.6396995708,\n            \"cpu_time\": 1642983.4123222788,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 421,\n            \"real_time\": 1661169.339654936,\n            \"cpu_time\": 1580800.4750593852,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9490973,\n            \"real_time\": 73.48123928932927,\n            \"cpu_time\": 73.46917960887671,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9486632,\n            \"real_time\": 73.78623677089479,\n            \"cpu_time\": 73.77971444449446,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9346969,\n            \"real_time\": 74.98375045263138,\n            \"cpu_time\": 74.97970732544377,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9258244,\n            \"real_time\": 79.12133499891443,\n            \"cpu_time\": 77.16430891214326,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9128594,\n            \"real_time\": 76.4508249536212,\n            \"cpu_time\": 76.43104732229287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9248056,\n            \"real_time\": 75.84535874184523,\n            \"cpu_time\": 75.80620186556021,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9197270,\n            \"real_time\": 76.02317959995017,\n            \"cpu_time\": 75.96058395589218,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11277,\n            \"real_time\": 63010.91451895219,\n            \"cpu_time\": 62939.3455706298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21150,\n            \"real_time\": 31981.0303524753,\n            \"cpu_time\": 31968.510638297423,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29926,\n            \"real_time\": 23687.892632935756,\n            \"cpu_time\": 23672.358484261153,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31234,\n            \"real_time\": 20984.331978956227,\n            \"cpu_time\": 20964.269706089504,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30385,\n            \"real_time\": 23111.937075953883,\n            \"cpu_time\": 22824.32121112414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34616,\n            \"real_time\": 22459.70551358884,\n            \"cpu_time\": 20933.152299514782,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36059,\n            \"real_time\": 18972.88241462847,\n            \"cpu_time\": 17634.51565489871,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6266100.446477399,\n            \"cpu_time\": 6265437.500000002,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 219,\n            \"real_time\": 3226491.4387012045,\n            \"cpu_time\": 3226118.7214611764,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 321,\n            \"real_time\": 2183089.04364914,\n            \"cpu_time\": 2182607.4766355176,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 395,\n            \"real_time\": 1776214.030311926,\n            \"cpu_time\": 1776093.670886061,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 416,\n            \"real_time\": 1702945.913376215,\n            \"cpu_time\": 1702115.3846153906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 389,\n            \"real_time\": 1673271.8508240497,\n            \"cpu_time\": 1665449.8714652993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 386,\n            \"real_time\": 1818948.8343141703,\n            \"cpu_time\": 1735090.6735751452,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"timed_task_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:38:06-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/timed_task_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            5.18701,\n            5.87451,\n            5.10254\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_dispenso<2,false>/manual_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 285.71428572250164,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.07214199999999993,\n            \"\\t1 System\": 0.044526,\n            \"mean\": 9.954080702737014e-06,\n            \"stddev\": 4.688011019863804e-07\n          },\n          {\n            \"name\": \"BM_dispenso<4,false>/manual_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 428.57142856789204,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.07397599999999982,\n            \"\\t1 System\": 0.057869000000000004,\n            \"mean\": 9.957789792679334e-06,\n            \"stddev\": 3.5240762570797743e-07\n          },\n          {\n            \"name\": \"BM_dispenso<6,false>/manual_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 285.71428572250164,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.074357,\n            \"\\t1 System\": 0.07025799999999999,\n            \"mean\": 9.977264795452481e-06,\n            \"stddev\": 1.919381593133926e-07\n          },\n          {\n            \"name\": \"BM_dispenso<2,true>/manual_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 428.57142856789204,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.071191,\n            \"\\t1 System\": 0.05306300000000003,\n            \"mean\": 9.97029440614132e-06,\n            \"stddev\": 4.79700518865891e-08\n          },\n          {\n            \"name\": \"BM_dispenso<4,true>/manual_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 571.4285714132826,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.07282100000000002,\n            \"\\t1 System\": 0.06379499999999994,\n            \"mean\": 9.871454516364591e-06,\n            \"stddev\": 4.525810659416707e-07\n          },\n          {\n            \"name\": \"BM_dispenso<6,true>/manual_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 571.4285714132826,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.07238100000000003,\n            \"\\t1 System\": 0.07241399999999998,\n            \"mean\": 1.282492521972484e-05,\n            \"stddev\": 2.684381062459743e-05\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 714.285714258673,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.18781499999999962,\n            \"\\t1 System\": 0.11230399999999996,\n            \"mean\": 9.979554878858283e-06,\n            \"stddev\": 4.5220154422806786e-08\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 428.57142856789204,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.16058799999999973,\n            \"\\t1 System\": 0.08947100000000008,\n            \"mean\": 9.894181556958926e-06,\n            \"stddev\": 5.092770671500604e-07\n          },\n          {\n            \"name\": \"BM_folly<2,false>/manual_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1285.714285735397,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0006410000000003357,\n            \"\\t1 System\": 0.0019329999999999625,\n            \"mean\": 0.000496583849638699,\n            \"stddev\": 0.0001415301833754346\n          },\n          {\n            \"name\": \"BM_folly<4,false>/manual_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.428571426178,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0008050000000001667,\n            \"\\t1 System\": 0.0021100000000000563,\n            \"mean\": 0.0008797843848215387,\n            \"stddev\": 0.00036541615103797984\n          },\n          {\n            \"name\": \"BM_folly<6,false>/manual_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.428571426178,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0010409999999998476,\n            \"\\t1 System\": 0.0022499999999998632,\n            \"mean\": 0.0013262439802661499,\n            \"stddev\": 0.000533976408747388\n          },\n          {\n            \"name\": \"BM_folly<2,true>/manual_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.4285713944573,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0007329999999998726,\n            \"\\t1 System\": 0.002018999999999993,\n            \"mean\": 0.000556840214172594,\n            \"stddev\": 0.0009912055774021107\n          },\n          {\n            \"name\": \"BM_folly<4,true>/manual_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.428571426178,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0007899999999998464,\n            \"\\t1 System\": 0.002138999999999891,\n            \"mean\": 0.0007247286991763077,\n            \"stddev\": 0.00024289857675277736\n          },\n          {\n            \"name\": \"BM_folly<6,true>/manual_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.4285714578984,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0007150000000000212,\n            \"\\t1 System\": 0.0020359999999999268,\n            \"mean\": 0.00108290358630563,\n            \"stddev\": 0.0003457069676219512\n          },\n          {\n            \"name\": \"BM_folly_mixed<false>/manual_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1428.5714285807876,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.0026290000000002145,\n            \"\\t1 System\": 0.00832300000000008,\n            \"mean\": 0.00016504625329437125,\n            \"stddev\": 0.00020945683632331378\n          },\n          {\n            \"name\": \"BM_folly_mixed<true>/manual_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 1571.428571426178,\n            \"time_unit\": \"ns\",\n            \"\\t0 User\": 0.002356000000000247,\n            \"\\t1 System\": 0.007269000000000192,\n            \"mean\": 0.00020931231811562877,\n            \"stddev\": 2.9049332138882714e-05\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"trivial_compute_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T10:38:34-07:00\",\n          \"host_name\": \"macos-bench\",\n          \"executable\": \"/tmp/dispenso-build/bin/trivial_compute_benchmark\",\n          \"num_cpus\": 12,\n          \"mhz_per_cpu\": 24,\n          \"cpu_scaling_enabled\": false,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 65536,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 131072,\n              \"num_sharing\": 0\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 4194304,\n              \"num_sharing\": 1\n            }\n          ],\n          \"load_avg\": [\n            3.71436,\n            5.4541,\n            4.97607\n          ],\n          \"library_version\": \"v1.9.5\",\n          \"library_build_type\": \"release\",\n          \"json_schema_version\": 1\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1275719,\n            \"real_time\": 548.900365180231,\n            \"cpu_time\": 548.8685204186816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21648549.500241645,\n            \"cpu_time\": 21646968.750000007,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 561459167.045541,\n            \"cpu_time\": 561423000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104946,\n            \"real_time\": 6661.6069209022635,\n            \"cpu_time\": 6652.4403026318305,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110878,\n            \"real_time\": 6561.512048899096,\n            \"cpu_time\": 6550.388715525174,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108577,\n            \"real_time\": 6409.191173429974,\n            \"cpu_time\": 6399.771590668362,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 109963,\n            \"real_time\": 6319.209270760749,\n            \"cpu_time\": 6307.612560588567,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115527,\n            \"real_time\": 6044.838730943729,\n            \"cpu_time\": 6034.364261168384,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122318,\n            \"real_time\": 5689.791837089,\n            \"cpu_time\": 5678.362955574813,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 127879,\n            \"real_time\": 5460.399416127546,\n            \"cpu_time\": 5453.522470460368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21669519.53040552,\n            \"cpu_time\": 21668156.250000015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 10992401.046678424,\n            \"cpu_time\": 10991562.500000024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 7441054.521861704,\n            \"cpu_time\": 7440031.914893617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123,\n            \"real_time\": 5626434.959069924,\n            \"cpu_time\": 5612634.146341458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 186,\n            \"real_time\": 3741124.774434514,\n            \"cpu_time\": 3740505.376344076,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 246,\n            \"real_time\": 2839112.8048164453,\n            \"cpu_time\": 2837414.634146331,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 304,\n            \"real_time\": 2344558.6611112384,\n            \"cpu_time\": 2241638.1578947343,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 561830165.9123971,\n            \"cpu_time\": 561788000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 285128250.0196248,\n            \"cpu_time\": 285112000.0000016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 192430114.7519145,\n            \"cpu_time\": 192418249.99999934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 144186466.79259837,\n            \"cpu_time\": 144153400.00000042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 96028398.85545628,\n            \"cpu_time\": 96008428.57142818,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 72845012.50833273,\n            \"cpu_time\": 72785600.00000027,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 58966774.25092397,\n            \"cpu_time\": 57100666.66666692,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1229491,\n            \"real_time\": 580.5775178253743,\n            \"cpu_time\": 580.5361730992754,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1216390,\n            \"real_time\": 574.6406038290687,\n            \"cpu_time\": 574.6027178783131,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1211502,\n            \"real_time\": 576.7989511892471,\n            \"cpu_time\": 576.637925484234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1217079,\n            \"real_time\": 575.9769562459976,\n            \"cpu_time\": 575.9404278604759,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1209871,\n            \"real_time\": 577.9981914972198,\n            \"cpu_time\": 577.9078926596295,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1206584,\n            \"real_time\": 580.669442029208,\n            \"cpu_time\": 580.4403174582069,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1202200,\n            \"real_time\": 579.405533944817,\n            \"cpu_time\": 578.863749792052,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21669511.719665024,\n            \"cpu_time\": 21667281.249999836,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 11017505.859854281,\n            \"cpu_time\": 11017281.250000011,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94,\n            \"real_time\": 7488596.181266326,\n            \"cpu_time\": 7487659.57446808,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 125,\n            \"real_time\": 5612743.663601578,\n            \"cpu_time\": 5608791.999999994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187,\n            \"real_time\": 3738881.6845658068,\n            \"cpu_time\": 3737155.0802138937,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 247,\n            \"real_time\": 2882029.6882384038,\n            \"cpu_time\": 2862542.5101214875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 312,\n            \"real_time\": 2278961.006548996,\n            \"cpu_time\": 2245532.05128203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 562269250.0473931,\n            \"cpu_time\": 562207999.9999982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 292155500.035733,\n            \"cpu_time\": 292139500.00000113,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 197789510.4791969,\n            \"cpu_time\": 197734999.99999976,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 148385433.3870113,\n            \"cpu_time\": 148340000.0000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 99080214.29354058,\n            \"cpu_time\": 99034285.71428512,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 74509717.54992174,\n            \"cpu_time\": 74454555.55555548,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 59913069.41723451,\n            \"cpu_time\": 58138083.33333329,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1213041,\n            \"real_time\": 570.0697667909037,\n            \"cpu_time\": 569.9535300125905,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1222612,\n            \"real_time\": 573.3583434461269,\n            \"cpu_time\": 573.3217079498637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1210961,\n            \"real_time\": 577.91274118162,\n            \"cpu_time\": 577.8815337570699,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1213761,\n            \"real_time\": 577.1878005612558,\n            \"cpu_time\": 577.1572821997065,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1207341,\n            \"real_time\": 578.9615013710945,\n            \"cpu_time\": 578.8621441663951,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1204604,\n            \"real_time\": 580.3538963612098,\n            \"cpu_time\": 580.1333882338083,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1197916,\n            \"real_time\": 581.0833497519056,\n            \"cpu_time\": 580.5023056708508,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21669522.124284413,\n            \"cpu_time\": 21667625.0000003,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 18929833.326035656,\n            \"cpu_time\": 18891432.432432197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55,\n            \"real_time\": 12668184.836564416,\n            \"cpu_time\": 12634472.727272727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72,\n            \"real_time\": 9689750.583169775,\n            \"cpu_time\": 9626361.111111097,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108,\n            \"real_time\": 6484188.268788987,\n            \"cpu_time\": 6409703.703703697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 144,\n            \"real_time\": 4873089.986277693,\n            \"cpu_time\": 4834187.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212,\n            \"real_time\": 3304771.0329004265,\n            \"cpu_time\": 3194551.886792449,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 564335832.9543843,\n            \"cpu_time\": 564277000.0000042,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 330473708.51272714,\n            \"cpu_time\": 330100999.9999991,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 228447625.02548596,\n            \"cpu_time\": 228323666.66667286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 175415989.4771874,\n            \"cpu_time\": 175114750.00000232,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 122168263.82791622,\n            \"cpu_time\": 121910333.33333461,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 96645541.72195494,\n            \"cpu_time\": 96256999.99999833,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 78237801.00120026,\n            \"cpu_time\": 70892666.66666718,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    }\n  ]\n}"
  },
  {
    "path": "results/windows_x64.json",
    "content": "{\n  \"machine_info\": {\n    \"timestamp\": \"2026-03-20T08:41:43.239873\",\n    \"platform\": \"Windows\",\n    \"platform_release\": \"11\",\n    \"platform_version\": \"10.0.26100\",\n    \"architecture\": \"AMD64\",\n    \"processor\": \"Intel64 Family 6 Model 85 Stepping 4, GenuineIntel\",\n    \"python_version\": \"3.12.4\",\n    \"build_system\": \"buck\",\n    \"cpu_model\": \"Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz\",\n    \"cpu_cores\": 64,\n    \"platform_id\": \"windows-xeon-64c\",\n    \"buck_mode\": \"VS2022 optimized\"\n  },\n  \"results\": [\n    {\n      \"name\": \"cascading_parallel_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:42:18-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"cascading_parallel_for_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36601,\n            \"real_time\": 18126.627687758595,\n            \"cpu_time\": 17929.83798256878,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/100000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388,\n            \"real_time\": 1871601.288658641,\n            \"cpu_time\": 1852448.4536082475,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial/10000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 220908233.33322382,\n            \"cpu_time\": 218750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 813,\n            \"real_time\": 877918.8191872248,\n            \"cpu_time\": 884071.3407134071,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1622,\n            \"real_time\": 414515.7829837441,\n            \"cpu_time\": 414226.26387176325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1875,\n            \"real_time\": 386387.0933331782,\n            \"cpu_time\": 375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2028,\n            \"real_time\": 355204.88165662787,\n            \"cpu_time\": 354413.2149901381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2235,\n            \"real_time\": 314773.19910519477,\n            \"cpu_time\": 279642.0581655481,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2465,\n            \"real_time\": 273383.04259647196,\n            \"cpu_time\": 266227.18052738335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2809,\n            \"real_time\": 251369.3841224314,\n            \"cpu_time\": 233624.06550373798,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3102,\n            \"real_time\": 218689.1682783568,\n            \"cpu_time\": 221631.20567375887,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3382,\n            \"real_time\": 207745.9195742041,\n            \"cpu_time\": 207902.12891780012,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3419,\n            \"real_time\": 209731.00321736166,\n            \"cpu_time\": 205652.23749634397,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3004,\n            \"real_time\": 229503.06258320724,\n            \"cpu_time\": 223660.11984021304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2770,\n            \"real_time\": 246281.44404327663,\n            \"cpu_time\": 242554.15162454874,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 142,\n            \"real_time\": 4912614.788729987,\n            \"cpu_time\": 4841549.295774648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 358,\n            \"real_time\": 1933018.4357528584,\n            \"cpu_time\": 1789455.30726257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 473,\n            \"real_time\": 1554351.3742066827,\n            \"cpu_time\": 1519556.0253699787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 562,\n            \"real_time\": 1211951.7793598466,\n            \"cpu_time\": 1223309.6085409252,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 737,\n            \"real_time\": 947158.3446412793,\n            \"cpu_time\": 911635.0067842605,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 928,\n            \"real_time\": 816632.6508622769,\n            \"cpu_time\": 808189.6551724138,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1180,\n            \"real_time\": 622457.1186436861,\n            \"cpu_time\": 609110.1694915254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1354,\n            \"real_time\": 526803.6189064309,\n            \"cpu_time\": 530834.564254062,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1557,\n            \"real_time\": 447190.9441234014,\n            \"cpu_time\": 451589.59537572257,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1697,\n            \"real_time\": 419638.83323490515,\n            \"cpu_time\": 414334.1190335887,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1657,\n            \"real_time\": 421511.16475537355,\n            \"cpu_time\": 414906.4574532287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1603,\n            \"real_time\": 433133.18777279864,\n            \"cpu_time\": 428883.3437305053,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 406839450.00000674,\n            \"cpu_time\": 375000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 128752666.66666599,\n            \"cpu_time\": 122395833.33333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 93706199.99992868,\n            \"cpu_time\": 93750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 63308690.909087256,\n            \"cpu_time\": 62500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 43474174.999971636,\n            \"cpu_time\": 42968750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33269757.142859038,\n            \"cpu_time\": 32738095.23809524,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 23640117.24135896,\n            \"cpu_time\": 23706896.55172414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 20076718.181812655,\n            \"cpu_time\": 19886363.636363637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17050264.99998894,\n            \"cpu_time\": 17187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 16541778.571427995,\n            \"cpu_time\": 16369047.61904762,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 18093715.384636126,\n            \"cpu_time\": 18028846.153846152,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 18486284.210523177,\n            \"cpu_time\": 18503289.47368421,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_task_group/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 904,\n            \"real_time\": 791001.9911504951,\n            \"cpu_time\": 795077.4336283186,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_task_group/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2124,\n            \"real_time\": 327248.2580038129,\n            \"cpu_time\": 331038.13559322036,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_task_group/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2278,\n            \"real_time\": 265875.1975417691,\n            \"cpu_time\": 267504.3898156278,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_task_group/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3033,\n            \"real_time\": 230665.2159576594,\n            \"cpu_time\": 231824.92581602375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_task_group/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3906,\n            \"real_time\": 179306.16999503932,\n            \"cpu_time\": 176011.26472094213,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_task_group/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4612,\n            \"real_time\": 154205.31222896997,\n            \"cpu_time\": 155843.4518647008,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_task_group/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5435,\n            \"real_time\": 129092.03311861103,\n            \"cpu_time\": 129369.82520699172,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_task_group/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6096,\n            \"real_time\": 112570.32480305883,\n            \"cpu_time\": 112778.87139107611,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_task_group/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7198,\n            \"real_time\": 98240.52514576392,\n            \"cpu_time\": 93341.90052792443,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_task_group/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7604,\n            \"real_time\": 90351.59126779658,\n            \"cpu_time\": 90412.94055760127,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_task_group/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7617,\n            \"real_time\": 91064.52671654278,\n            \"cpu_time\": 92309.96455297362,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_task_group/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8750,\n            \"real_time\": 82600.54857143718,\n            \"cpu_time\": 82142.85714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_task_group/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131,\n            \"real_time\": 5489421.37404694,\n            \"cpu_time\": 5486641.221374046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_task_group/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 405,\n            \"real_time\": 1714686.9135799925,\n            \"cpu_time\": 1658950.6172839506,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_task_group/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 572,\n            \"real_time\": 1231472.3776223848,\n            \"cpu_time\": 1229239.5104895106,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_task_group/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 713,\n            \"real_time\": 953330.4347833862,\n            \"cpu_time\": 942321.178120617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_task_group/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1033,\n            \"real_time\": 740634.8499515749,\n            \"cpu_time\": 741166.5053242982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_task_group/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1239,\n            \"real_time\": 574660.2098466336,\n            \"cpu_time\": 567493.9467312349,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_task_group/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1795,\n            \"real_time\": 411137.214484413,\n            \"cpu_time\": 409122.5626740947,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_task_group/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2222,\n            \"real_time\": 315095.1845182348,\n            \"cpu_time\": 316437.8937893789,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_task_group/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2694,\n            \"real_time\": 259162.0267261534,\n            \"cpu_time\": 260996.6592427617,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb_task_group/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2989,\n            \"real_time\": 234158.54800928867,\n            \"cpu_time\": 235237.53763800603,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb_task_group/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3207,\n            \"real_time\": 216791.39382621433,\n            \"cpu_time\": 219246.95977549112,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/100000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb_task_group/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3493,\n            \"real_time\": 201929.6593186341,\n            \"cpu_time\": 201295.44803893502,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb_task_group/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 387399300.0001974,\n            \"cpu_time\": 390625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb_task_group/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 128894866.66654193,\n            \"cpu_time\": 127604166.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb_task_group/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 83954150.00006779,\n            \"cpu_time\": 82031250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb_task_group/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 66419772.72730318,\n            \"cpu_time\": 66761363.63636363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb_task_group/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 42381318.75001727,\n            \"cpu_time\": 41992187.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb_task_group/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 32760295.238100905,\n            \"cpu_time\": 32738095.23809524,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb_task_group/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30,\n            \"real_time\": 23412256.66665802,\n            \"cpu_time\": 22916666.666666668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/16/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb_task_group/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 20146739.99999234,\n            \"cpu_time\": 20089285.714285713,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/24/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb_task_group/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 17918942.10526535,\n            \"cpu_time\": 17680921.05263158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/32/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb_task_group/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 17288219.04762732,\n            \"cpu_time\": 17113095.23809524,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/48/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb_task_group/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17730107.50000594,\n            \"cpu_time\": 17187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_task_group/64/10000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb_task_group/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 17831479.487190686,\n            \"cpu_time\": 17628205.128205128,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_blocking/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46945,\n            \"real_time\": 14741.759505814864,\n            \"cpu_time\": 14644.797102992865,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_blocking/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47058,\n            \"real_time\": 14866.492413625363,\n            \"cpu_time\": 14277.593607888139,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_blocking/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47044,\n            \"real_time\": 14865.525890659896,\n            \"cpu_time\": 14946.114275996939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_blocking/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47017,\n            \"real_time\": 14921.40076993976,\n            \"cpu_time\": 14290.044026628666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_blocking/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47217,\n            \"real_time\": 14880.833174482921,\n            \"cpu_time\": 14560.433742084419,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_blocking/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46961,\n            \"real_time\": 14875.458359071257,\n            \"cpu_time\": 14639.807499840294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_blocking/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46700,\n            \"real_time\": 14904.42826552466,\n            \"cpu_time\": 14387.044967880085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_blocking/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46694,\n            \"real_time\": 14960.11693150802,\n            \"cpu_time\": 14388.893648006167,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_blocking/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46556,\n            \"real_time\": 15067.048285931416,\n            \"cpu_time\": 15102.77944840622,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_blocking/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45969,\n            \"real_time\": 15164.856751282998,\n            \"cpu_time\": 14615.828058039113,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_blocking/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45753,\n            \"real_time\": 15460.382925693075,\n            \"cpu_time\": 15367.844731493016,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_blocking/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44920,\n            \"real_time\": 15871.433659830913,\n            \"cpu_time\": 16000.667853962601,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_blocking/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 444,\n            \"real_time\": 1526928.6036036154,\n            \"cpu_time\": 1513231.981981982,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_blocking/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 846,\n            \"real_time\": 830264.0661934267,\n            \"cpu_time\": 812647.7541371158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_blocking/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1246,\n            \"real_time\": 552650.9630814242,\n            \"cpu_time\": 539225.521669342,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_blocking/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1672,\n            \"real_time\": 418455.98086170544,\n            \"cpu_time\": 420529.3062200957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_blocking/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1887,\n            \"real_time\": 305991.36195059965,\n            \"cpu_time\": 306372.54901960783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_blocking/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2263,\n            \"real_time\": 234318.33848856762,\n            \"cpu_time\": 234754.75033141847,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_blocking/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2844,\n            \"real_time\": 231394.4796063695,\n            \"cpu_time\": 230748.94514767933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_blocking/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3189,\n            \"real_time\": 194020.85293197815,\n            \"cpu_time\": 195986.20257133897,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_blocking/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2946,\n            \"real_time\": 225480.14256624988,\n            \"cpu_time\": 222759.67413441956,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_blocking/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2264,\n            \"real_time\": 275664.885158758,\n            \"cpu_time\": 262257.0671378092,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_blocking/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2035,\n            \"real_time\": 299774.4963143794,\n            \"cpu_time\": 291769.0417690418,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_blocking/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1714,\n            \"real_time\": 371656.00933474954,\n            \"cpu_time\": 373760.2100350058,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_blocking/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 199952066.66650724,\n            \"cpu_time\": 203125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_blocking/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102800599.99994202,\n            \"cpu_time\": 95982142.85714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_blocking/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 68918229.99996294,\n            \"cpu_time\": 68750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_blocking/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 51819028.57137694,\n            \"cpu_time\": 51339285.71428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_blocking/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 40618217.64705254,\n            \"cpu_time\": 40441176.47058824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_blocking/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 29560056.521760367,\n            \"cpu_time\": 28532608.695652176,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_blocking/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 23345778.571410846,\n            \"cpu_time\": 22879464.285714287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/16/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_blocking/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 22031491.428554416,\n            \"cpu_time\": 21875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/24/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_blocking/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 20624918.421067137,\n            \"cpu_time\": 20559210.52631579,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/32/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_blocking/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19562622.222211856,\n            \"cpu_time\": 19531250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/48/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_blocking/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 17898750.000002015,\n            \"cpu_time\": 17269736.842105262,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_blocking/64/10000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_blocking/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 19239791.89187604,\n            \"cpu_time\": 18158783.783783782,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_cascaded/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49037,\n            \"real_time\": 14243.51815976715,\n            \"cpu_time\": 14338.662642494442,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_cascaded/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47439,\n            \"real_time\": 14454.417251627463,\n            \"cpu_time\": 14162.925019498725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_cascaded/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48357,\n            \"real_time\": 14459.798994977096,\n            \"cpu_time\": 14217.176417064748,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_cascaded/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48406,\n            \"real_time\": 14461.002768250732,\n            \"cpu_time\": 14525.575341899765,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_cascaded/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48421,\n            \"real_time\": 14487.468247245839,\n            \"cpu_time\": 14198.384998244563,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_cascaded/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44576,\n            \"real_time\": 14981.62688442219,\n            \"cpu_time\": 14020.99784637473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_cascaded/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48026,\n            \"real_time\": 14597.607545926017,\n            \"cpu_time\": 13989.818015241744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_cascaded/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48212,\n            \"real_time\": 14578.580021558022,\n            \"cpu_time\": 14584.02472413507,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_cascaded/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47482,\n            \"real_time\": 14678.90569058702,\n            \"cpu_time\": 14150.098984878481,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_cascaded/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47467,\n            \"real_time\": 14820.44156991453,\n            \"cpu_time\": 14812.922662059957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_cascaded/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46491,\n            \"real_time\": 15077.182680519616,\n            \"cpu_time\": 15123.894947409175,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_cascaded/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45632,\n            \"real_time\": 15202.662605176862,\n            \"cpu_time\": 15066.181626928472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_cascaded/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 426,\n            \"real_time\": 1551691.7840362117,\n            \"cpu_time\": 1577171.3615023475,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_cascaded/2/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 761,\n            \"real_time\": 875754.9277272715,\n            \"cpu_time\": 862352.1681997372,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_cascaded/3/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1208,\n            \"real_time\": 581173.9238408143,\n            \"cpu_time\": 582057.119205298,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_cascaded/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1546,\n            \"real_time\": 407334.73479957413,\n            \"cpu_time\": 394162.35446313064,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_cascaded/6/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2304,\n            \"real_time\": 306607.85590283823,\n            \"cpu_time\": 305175.78125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_cascaded/8/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2955,\n            \"real_time\": 253322.8764805983,\n            \"cpu_time\": 253807.10659898477,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_cascaded/12/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4347,\n            \"real_time\": 187819.57671968502,\n            \"cpu_time\": 190504.94593972855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_cascaded/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4520,\n            \"real_time\": 179148.2964603572,\n            \"cpu_time\": 179756.6371681416,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_cascaded/24/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3667,\n            \"real_time\": 171820.64357765776,\n            \"cpu_time\": 174700.02727024816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_cascaded/32/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3850,\n            \"real_time\": 190077.3506493753,\n            \"cpu_time\": 186688.3116883117,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_cascaded/48/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3535,\n            \"real_time\": 218409.92927868612,\n            \"cpu_time\": 221004.243281471,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_cascaded/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3166,\n            \"real_time\": 228597.69425139533,\n            \"cpu_time\": 227021.4782059381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_cascaded/1/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 196639033.33336446,\n            \"cpu_time\": 197916666.66666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_cascaded/2/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 132378919.99997373,\n            \"cpu_time\": 131250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_cascaded/3/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 74751255.55558608,\n            \"cpu_time\": 74652777.77777778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_cascaded/4/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 52591566.666706055,\n            \"cpu_time\": 52083333.333333336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_cascaded/6/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 39176384.21051762,\n            \"cpu_time\": 38651315.78947368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_cascaded/8/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 30249945.4545465,\n            \"cpu_time\": 29119318.181818184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_cascaded/12/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 24379596.428583942,\n            \"cpu_time\": 24553571.42857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/16/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_cascaded/16/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 20655768.750003744,\n            \"cpu_time\": 20019531.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/24/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_cascaded/24/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 17909888.571427602,\n            \"cpu_time\": 17857142.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/32/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_cascaded/32/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 18614663.157892976,\n            \"cpu_time\": 17680921.05263158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/48/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_cascaded/48/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 18371323.076910183,\n            \"cpu_time\": 18429487.17948718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_cascaded/64/10000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_cascaded/64/10000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 18697297.29728656,\n            \"cpu_time\": 17314189.18918919,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"concurrent_vector_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:44:56-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"concurrent_vector_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_std_push_back_serial\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 7517800.892864151,\n            \"cpu_time\": 6975446.428571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_push_back_serial\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 29579995.999993116,\n            \"cpu_time\": 30000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 14866904.000009527,\n            \"cpu_time\": 15000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 13250582.142859457,\n            \"cpu_time\": 13113839.285714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 9366960.000006657,\n            \"cpu_time\": 9375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 280,\n            \"real_time\": 2494382.5000004186,\n            \"cpu_time\": 2511160.714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_push_back_serial_reserve\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2753903.787878919,\n            \"cpu_time\": 2781723.484848485,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_reserve\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 15424524.000009114,\n            \"cpu_time\": 15312500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 13223976.78572023,\n            \"cpu_time\": 13392857.142857144,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 8904556.000003746,\n            \"cpu_time\": 8750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_push_back_serial_grow_by_alternative_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2587664.3939379086,\n            \"cpu_time\": 2604166.6666666665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4073,\n            \"real_time\": 156543.87429409043,\n            \"cpu_time\": 157285.7844340781,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 560,\n            \"real_time\": 1169003.5714293248,\n            \"cpu_time\": 1171875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 498,\n            \"real_time\": 1340234.136545675,\n            \"cpu_time\": 1349146.5863453816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 673235.602677989,\n            \"cpu_time\": 662667.4107142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_iterate_reverse\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 677335.9821425272,\n            \"cpu_time\": 669642.8571428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_iterate_reverse\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 448,\n            \"real_time\": 1645808.705356038,\n            \"cpu_time\": 1639229.9107142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_iterate_reverse\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 249,\n            \"real_time\": 2751136.1445778976,\n            \"cpu_time\": 2698293.172690763,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_iterate_reverse\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_iterate_reverse\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6679877.678574746,\n            \"cpu_time\": 6556919.642857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_lower_bound\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 56842154.545434326,\n            \"cpu_time\": 55397727.27272727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_lower_bound\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 179241824.99996278,\n            \"cpu_time\": 171875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_lower_bound\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 102715500.00000691,\n            \"cpu_time\": 104166666.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_lower_bound\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_lower_bound\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 227708700.00022113,\n            \"cpu_time\": 229166666.66666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_index\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4073,\n            \"real_time\": 159802.67616011872,\n            \"cpu_time\": 157285.7844340781,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_index\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 747,\n            \"real_time\": 1016580.3212857594,\n            \"cpu_time\": 1024933.0655957162,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_index\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2669900.757575416,\n            \"cpu_time\": 2663352.272727273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_index\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_index\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 3376679.3427198986,\n            \"cpu_time\": 3374413.145539906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_random\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 280,\n            \"real_time\": 2473420.714285827,\n            \"cpu_time\": 2399553.5714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_random\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 6518578.571428536,\n            \"cpu_time\": 6556919.642857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_random\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 236,\n            \"real_time\": 3134037.7118656267,\n            \"cpu_time\": 3111758.474576271,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_random\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_random\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 195,\n            \"real_time\": 3642050.2564093717,\n            \"cpu_time\": 3605769.230769231,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 328254399.9998779,\n            \"cpu_time\": 289062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 736798500.0000771,\n            \"cpu_time\": 593750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel\",\n            \"family_index\": 33,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 58401463.6363215,\n            \"cpu_time\": 58238636.36363637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel\",\n            \"family_index\": 34,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 44388806.66669623,\n            \"cpu_time\": 41666666.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_reserve\",\n            \"family_index\": 35,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 324387349.9995971,\n            \"cpu_time\": 296875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_reserve\",\n            \"family_index\": 36,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 58540649.9999408,\n            \"cpu_time\": 56250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_reserve\",\n            \"family_index\": 37,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_reserve\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 44234699.99999404,\n            \"cpu_time\": 43198529.4117647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_clear\",\n            \"family_index\": 38,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 329473050.0001606,\n            \"cpu_time\": 304687500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_clear\",\n            \"family_index\": 39,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 707295700.0000315,\n            \"cpu_time\": 578125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_clear\",\n            \"family_index\": 40,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 60796890.90909762,\n            \"cpu_time\": 58238636.36363637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_clear\",\n            \"family_index\": 41,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_clear\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41515088.235267766,\n            \"cpu_time\": 41360294.11764706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_10\",\n            \"family_index\": 42,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 56859089.99994353,\n            \"cpu_time\": 50000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_10\",\n            \"family_index\": 43,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 282806100.00001615,\n            \"cpu_time\": 187500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_10\",\n            \"family_index\": 44,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 12945349.999995414,\n            \"cpu_time\": 13113839.285714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"family_index\": 45,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_10\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 5652936.607142627,\n            \"cpu_time\": 5440848.214285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_100\",\n            \"family_index\": 46,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 21150102.439028937,\n            \"cpu_time\": 18673780.48780488,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_100\",\n            \"family_index\": 47,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 73043863.41463503,\n            \"cpu_time\": 20198170.731707316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_100\",\n            \"family_index\": 48,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 4198957.558142062,\n            \"cpu_time\": 4178779.069767442,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"family_index\": 49,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_100\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 643807.8000001042,\n            \"cpu_time\": 640625.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_parallel_grow_by_max\",\n            \"family_index\": 50,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 448,\n            \"real_time\": 3556605.1339291753,\n            \"cpu_time\": 1429966.517857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_deque_parallel_grow_by_max\",\n            \"family_index\": 51,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_deque_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 29776539.99999651,\n            \"cpu_time\": 14930555.555555556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_parallel_grow_by_max\",\n            \"family_index\": 52,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 448,\n            \"real_time\": 1595859.8214293066,\n            \"cpu_time\": 1569475.4464285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"family_index\": 53,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_parallel_grow_by_max\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11200,\n            \"real_time\": 61743.41964286408,\n            \"cpu_time\": 61383.92857142857,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_each_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:45:54-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"for_each_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7466667,\n            \"real_time\": 84.04830428352788,\n            \"cpu_time\": 83.70535340601101,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2240,\n            \"real_time\": 309369.955356991,\n            \"cpu_time\": 313895.08928571426,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 67237781.81822127,\n            \"cpu_time\": 65340909.09090909,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 646207,\n            \"real_time\": 1084.4699918143858,\n            \"cpu_time\": 1063.9005767501744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 460153,\n            \"real_time\": 1519.7095313950595,\n            \"cpu_time\": 1494.0682772903795,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 447192,\n            \"real_time\": 1572.0795541952234,\n            \"cpu_time\": 1502.4307232687527,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197920,\n            \"real_time\": 3625.7103880354125,\n            \"cpu_time\": 3631.5177849636216,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 118455,\n            \"real_time\": 5356.712675701717,\n            \"cpu_time\": 5408.171879616732,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 131089,\n            \"real_time\": 5282.134275190921,\n            \"cpu_time\": 5125.33469627505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 96102,\n            \"real_time\": 7214.105845864306,\n            \"cpu_time\": 6991.26969261826,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94876,\n            \"real_time\": 9071.630338554369,\n            \"cpu_time\": 9057.875542813777,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 55603,\n            \"real_time\": 12871.75152419334,\n            \"cpu_time\": 12926.460802474687,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37995,\n            \"real_time\": 18384.761152789448,\n            \"cpu_time\": 17683.2477957626,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30094,\n            \"real_time\": 23181.046055678067,\n            \"cpu_time\": 23364.291885425668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24309,\n            \"real_time\": 28533.958616168267,\n            \"cpu_time\": 26996.17425644823,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 676,\n            \"real_time\": 1034970.1183433633,\n            \"cpu_time\": 993897.9289940828,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1176,\n            \"real_time\": 595689.3707482524,\n            \"cpu_time\": 584608.8435374149,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1699,\n            \"real_time\": 405083.57857527357,\n            \"cpu_time\": 404649.79399646854,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1127796.8000003968,\n            \"cpu_time\": 1140625.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3300,\n            \"real_time\": 216627.5757576152,\n            \"cpu_time\": 213068.18181818182,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4104,\n            \"real_time\": 171827.0224171569,\n            \"cpu_time\": 167519.49317738792,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1713,\n            \"real_time\": 402656.97606550186,\n            \"cpu_time\": 401342.6736719206,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3284,\n            \"real_time\": 305066.35200955323,\n            \"cpu_time\": 304506.69914738124,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3155,\n            \"real_time\": 213281.2044373861,\n            \"cpu_time\": 212955.62599049127,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3168,\n            \"real_time\": 216792.99242427622,\n            \"cpu_time\": 217013.88888888888,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4604,\n            \"real_time\": 168218.04952229635,\n            \"cpu_time\": 169689.40052128583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3950,\n            \"real_time\": 160331.34177218293,\n            \"cpu_time\": 146360.7594936709,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109234616.66667815,\n            \"cpu_time\": 109375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 66536019.999966815,\n            \"cpu_time\": 65625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 44435031.250031896,\n            \"cpu_time\": 44921875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 76661340.00000966,\n            \"cpu_time\": 76562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 21261312.12119645,\n            \"cpu_time\": 21306818.181818184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 35425519.99998977,\n            \"cpu_time\": 32812500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_for_each_n/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 27262089.47368784,\n            \"cpu_time\": 27960526.315789472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_for_each_n/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 28305817.391296647,\n            \"cpu_time\": 27853260.86956522,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_for_each_n/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 20998077.41935013,\n            \"cpu_time\": 20665322.580645163,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_for_each_n/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39,\n            \"real_time\": 18547441.025638808,\n            \"cpu_time\": 18429487.17948718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_for_each_n/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 17987158.139539834,\n            \"cpu_time\": 17805232.558139537,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_for_each_n/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 16404246.341463897,\n            \"cpu_time\": 16006097.56097561,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_deque/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87191,\n            \"real_time\": 8009.351882652337,\n            \"cpu_time\": 7705.783853838126,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_deque/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17040,\n            \"real_time\": 39165.639671349956,\n            \"cpu_time\": 38512.32394366197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_deque/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15411,\n            \"real_time\": 33065.22613718145,\n            \"cpu_time\": 32444.35792615664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_deque/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12773,\n            \"real_time\": 58973.15430992767,\n            \"cpu_time\": 59940.890941830425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_deque/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12119,\n            \"real_time\": 56404.99216112503,\n            \"cpu_time\": 55439.80526446077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_deque/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11957,\n            \"real_time\": 52330.86058374619,\n            \"cpu_time\": 52270.63644726938,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_deque/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12943,\n            \"real_time\": 53960.34922351268,\n            \"cpu_time\": 54324.73151510469,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_deque/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13636,\n            \"real_time\": 61547.38193015489,\n            \"cpu_time\": 61876.65004400117,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_deque/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10919,\n            \"real_time\": 62366.87425594681,\n            \"cpu_time\": 61532.649510028394,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_deque/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10956,\n            \"real_time\": 67295.12595833918,\n            \"cpu_time\": 65603.3223804308,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_deque/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10498,\n            \"real_time\": 62915.879215068206,\n            \"cpu_time\": 62511.90702991046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_deque/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11010,\n            \"real_time\": 63817.547683906836,\n            \"cpu_time\": 63862.39782016349,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_deque/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 87,\n            \"real_time\": 8026022.988501765,\n            \"cpu_time\": 7902298.850574712,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_deque/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 20114088.57142669,\n            \"cpu_time\": 20089285.714285713,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_deque/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 55972607.69228832,\n            \"cpu_time\": 56490384.615384616,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_deque/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 62716099.99996806,\n            \"cpu_time\": 61079545.45454545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_deque/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 49736192.8571211,\n            \"cpu_time\": 49107142.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_deque/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 58105458.333329804,\n            \"cpu_time\": 57291666.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_deque/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 53120723.07690239,\n            \"cpu_time\": 52884615.384615384,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_deque/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 53590591.66668582,\n            \"cpu_time\": 53385416.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_deque/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 58538541.66662132,\n            \"cpu_time\": 58593750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_deque/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 56744900.00001242,\n            \"cpu_time\": 57291666.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_deque/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47827500.00000911,\n            \"cpu_time\": 47916666.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_deque/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 43286262.50003254,\n            \"cpu_time\": 42968750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_for_each_n_deque/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 851916500.0006979,\n            \"cpu_time\": 828125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_for_each_n_deque/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4051674400.0005927,\n            \"cpu_time\": 4031250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_for_each_n_deque/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4515227100.000629,\n            \"cpu_time\": 4468750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_for_each_n_deque/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4694814299.999962,\n            \"cpu_time\": 4640625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_for_each_n_deque/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4861839099.999997,\n            \"cpu_time\": 4828125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_for_each_n_deque/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5035947000.000306,\n            \"cpu_time\": 5015625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_for_each_n_deque/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5235028399.999464,\n            \"cpu_time\": 5187500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_for_each_n_deque/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5249350699.999923,\n            \"cpu_time\": 5234375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_for_each_n_deque/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5716208199.999528,\n            \"cpu_time\": 5703125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_for_each_n_deque/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 6091953799.999828,\n            \"cpu_time\": 5921875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_for_each_n_deque/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4860996599.999453,\n            \"cpu_time\": 4843750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_deque/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_for_each_n_deque/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4421639799.9998665,\n            \"cpu_time\": 4218750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_list/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70257,\n            \"real_time\": 10174.795394057788,\n            \"cpu_time\": 10007.899568726249,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_list/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30596,\n            \"real_time\": 23197.568309595623,\n            \"cpu_time\": 23491.632893188653,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_list/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28899,\n            \"real_time\": 23822.924668656386,\n            \"cpu_time\": 23789.750510398284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_list/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20372,\n            \"real_time\": 28461.893775754656,\n            \"cpu_time\": 28378.411545258197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_list/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22494,\n            \"real_time\": 28092.8603182864,\n            \"cpu_time\": 27090.557481995198,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_list/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24638,\n            \"real_time\": 23696.57033848705,\n            \"cpu_time\": 23464.769867684066,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_list/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23677,\n            \"real_time\": 24074.114119192094,\n            \"cpu_time\": 24417.15588968197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_list/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23162,\n            \"real_time\": 31412.114670590858,\n            \"cpu_time\": 31706.027113375356,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_list/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19082,\n            \"real_time\": 33222.74918770779,\n            \"cpu_time\": 33572.214652552146,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_list/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18440,\n            \"real_time\": 39872.901301540194,\n            \"cpu_time\": 38977.76572668113,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_list/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16035,\n            \"real_time\": 43408.90551919424,\n            \"cpu_time\": 43849.391955098225,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_list/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12444,\n            \"real_time\": 49250.57859209888,\n            \"cpu_time\": 43946.882031501125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_list/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 17695149.99998339,\n            \"cpu_time\": 17795138.888888888,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_list/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31141654.545453176,\n            \"cpu_time\": 30539772.727272727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_list/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 30434668.181814313,\n            \"cpu_time\": 30539772.727272727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_list/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 29903634.782583497,\n            \"cpu_time\": 29891304.347826086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_list/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 44486087.49999039,\n            \"cpu_time\": 43945312.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_list/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 34372458.33333691,\n            \"cpu_time\": 33203125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_list/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 32176096.000002872,\n            \"cpu_time\": 31875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_list/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 41001626.08697049,\n            \"cpu_time\": 41440217.39130435,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_list/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 36350609.09089754,\n            \"cpu_time\": 36221590.90909091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_list/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33771790.476185694,\n            \"cpu_time\": 33482142.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_list/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 32093731.578961045,\n            \"cpu_time\": 32072368.42105263,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_list/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_list/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 33987964.999960236,\n            \"cpu_time\": 32812500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_for_each_n_set/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 220680,\n            \"real_time\": 3307.6101141892304,\n            \"cpu_time\": 3327.7823092260287,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_for_each_n_set/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 99121,\n            \"real_time\": 6816.580744751944,\n            \"cpu_time\": 6778.33153418549,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_for_each_n_set/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 94229,\n            \"real_time\": 6890.116630755298,\n            \"cpu_time\": 6798.597034883104,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_for_each_n_set/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102989,\n            \"real_time\": 8672.007690145374,\n            \"cpu_time\": 8647.768208255251,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_for_each_n_set/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105705,\n            \"real_time\": 6706.4651624836015,\n            \"cpu_time\": 6799.58374722104,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_for_each_n_set/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74946,\n            \"real_time\": 10548.869852954203,\n            \"cpu_time\": 10632.655511968618,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_for_each_n_set/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73297,\n            \"real_time\": 11562.660136162458,\n            \"cpu_time\": 11511.385186296848,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/16/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_for_each_n_set/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51856,\n            \"real_time\": 12325.000000005935,\n            \"cpu_time\": 12052.60721999383,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/24/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_for_each_n_set/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43992,\n            \"real_time\": 15582.740043637485,\n            \"cpu_time\": 15627.841425713767,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/32/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_for_each_n_set/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34138,\n            \"real_time\": 19274.075809962564,\n            \"cpu_time\": 19223.446013240376,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/48/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_for_each_n_set/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30144,\n            \"real_time\": 26063.528397031692,\n            \"cpu_time\": 25917.26380042463,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/64/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_for_each_n_set/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22325,\n            \"real_time\": 29953.151175792107,\n            \"cpu_time\": 29395.296752519596,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_for_each_n_set/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 218450,\n            \"real_time\": 3201.5060654608983,\n            \"cpu_time\": 3218.6999313344013,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_for_each_n_set/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100545,\n            \"real_time\": 6997.247003823731,\n            \"cpu_time\": 6837.734347804466,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_for_each_n_set/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93447,\n            \"real_time\": 7690.123813500883,\n            \"cpu_time\": 7691.525677656854,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_for_each_n_set/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101395,\n            \"real_time\": 8664.049509344155,\n            \"cpu_time\": 8475.516544208294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_for_each_n_set/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105507,\n            \"real_time\": 6846.994038311776,\n            \"cpu_time\": 6664.249765418408,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_for_each_n_set/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 72022,\n            \"real_time\": 10638.479908910924,\n            \"cpu_time\": 10630.43236788759,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_for_each_n_set/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76376,\n            \"real_time\": 11471.217398130926,\n            \"cpu_time\": 11456.478474913585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_for_each_n_set/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52940,\n            \"real_time\": 12281.87570834865,\n            \"cpu_time\": 12100.963354741216,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_for_each_n_set/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42969,\n            \"real_time\": 16018.497056011467,\n            \"cpu_time\": 15999.906909632526,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_for_each_n_set/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36676,\n            \"real_time\": 20795.44116044832,\n            \"cpu_time\": 20449.34016795725,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_for_each_n_set/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28420,\n            \"real_time\": 23569.208303997504,\n            \"cpu_time\": 23640.921885995776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_for_each_n_set/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_for_each_n_set/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23257,\n            \"real_time\": 30612.809046745686,\n            \"cpu_time\": 29560.992389388142,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"for_latency_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:49:32-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"for_latency_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 47151561.53843754,\n            \"cpu_time\": 10817307.692307692,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.009866256676734618,\n            \"stddev\": 0.00017188413544657612\n          },\n          {\n            \"name\": \"BM_tbb/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47286566.66666211,\n            \"cpu_time\": 6250000.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.01162628341329158,\n            \"stddev\": 0.00038164494907208036\n          },\n          {\n            \"name\": \"BM_tbb/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47342366.66669555,\n            \"cpu_time\": 8333333.333333333,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.005110984746715985,\n            \"stddev\": 2.8214285872140384e-05\n          },\n          {\n            \"name\": \"BM_tbb/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47161833.33330264,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0035127603199119526,\n            \"stddev\": 5.078153538875011e-05\n          },\n          {\n            \"name\": \"BM_tbb/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47164519.99999359,\n            \"cpu_time\": 8333333.333333333,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0026620443730280387,\n            \"stddev\": 4.993449566211268e-05\n          },\n          {\n            \"name\": \"BM_tbb/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 45003046.66665518,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0018042646933584669,\n            \"stddev\": 2.1748562041657222e-05\n          },\n          {\n            \"name\": \"BM_tbb/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 38977068.42101462,\n            \"cpu_time\": 1644736.8421052631,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0013987661052995367,\n            \"stddev\": 6.0021690135250075e-05\n          },\n          {\n            \"name\": \"BM_tbb/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33855600.00000017,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0009833384000168216,\n            \"stddev\": 3.800137869086121e-05\n          },\n          {\n            \"name\": \"BM_tbb/16/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 31342742.85713175,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007570424763149017,\n            \"stddev\": 1.6869748052078347e-05\n          },\n          {\n            \"name\": \"BM_tbb/24/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 32234536.363665197,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005633357816970437,\n            \"stddev\": 1.8899260504457734e-05\n          },\n          {\n            \"name\": \"BM_tbb/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31261881.818202462,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005073009817599748,\n            \"stddev\": 2.1597028407683795e-05\n          },\n          {\n            \"name\": \"BM_tbb/48/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31327159.09094424,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00041888141814442036,\n            \"stddev\": 3.08616041150368e-05\n          },\n          {\n            \"name\": \"BM_tbb/64/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31395763.63636562,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00041174054529785116,\n            \"stddev\": 5.710726322374978e-05\n          },\n          {\n            \"name\": \"BM_dispenso/1/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18,\n            \"real_time\": 39721527.77775288,\n            \"cpu_time\": 9548611.111111112,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.009355069911129653,\n            \"stddev\": 0.000533704182538213\n          },\n          {\n            \"name\": \"BM_dispenso/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 35242369.99996901,\n            \"cpu_time\": 3125000.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.004754647199888495,\n            \"stddev\": 0.0005980738957520091\n          },\n          {\n            \"name\": \"BM_dispenso/3/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33481509.523794338,\n            \"cpu_time\": 2976190.476190476,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.003077694933294662,\n            \"stddev\": 9.262964406965801e-05\n          },\n          {\n            \"name\": \"BM_dispenso/4/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 32807752.380947582,\n            \"cpu_time\": 2232142.8571428573,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.002276384152450884,\n            \"stddev\": 8.054854388480215e-05\n          },\n          {\n            \"name\": \"BM_dispenso/6/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31958850.000013296,\n            \"cpu_time\": 1420454.5454545454,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0015414021454902963,\n            \"stddev\": 2.5848883903370683e-05\n          },\n          {\n            \"name\": \"BM_dispenso/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31791295.454530135,\n            \"cpu_time\": 710227.2727272727,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0012085252364654893,\n            \"stddev\": 6.189326538413849e-05\n          },\n          {\n            \"name\": \"BM_dispenso/12/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31275231.818199243,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.000826921236280627,\n            \"stddev\": 2.6505786765486095e-05\n          },\n          {\n            \"name\": \"BM_dispenso/16/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31198531.818187226,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0006963082545222609,\n            \"stddev\": 6.463564003765823e-05\n          },\n          {\n            \"name\": \"BM_dispenso/24/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31174109.09089813,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.000561423636513196,\n            \"stddev\": 6.30445086674893e-05\n          },\n          {\n            \"name\": \"BM_dispenso/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 31008299.999998797,\n            \"cpu_time\": 2717391.304347826,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.000515460069476356,\n            \"stddev\": 6.020050637735911e-05\n          },\n          {\n            \"name\": \"BM_dispenso/48/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31082345.454540864,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00045824632723617304,\n            \"stddev\": 5.80102419487137e-05\n          },\n          {\n            \"name\": \"BM_dispenso/64/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 31251334.782609772,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.000475727617571386,\n            \"stddev\": 6.34318979574684e-05\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"future_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:50:02-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"future_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 340,\n            \"real_time\": 2028086.1764711197,\n            \"cpu_time\": 1976102.9411764706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 16244425.581410112,\n            \"cpu_time\": 15988372.093023255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 130485699.99991742,\n            \"cpu_time\": 131250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async deadlocks on Windows threadpool\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async deadlocks on Windows threadpool\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_std_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"error_occurred\": true,\n            \"error_message\": \"std::async deadlocks on Windows threadpool\",\n            \"iterations\": 0,\n            \"real_time\": 0.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 26942503.70371231,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 227501300.00016117,\n            \"cpu_time\": 5208333.333333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1784169900.0000517,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 666,\n            \"real_time\": 1055777.927928472,\n            \"cpu_time\": 164226.72672672672,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101,\n            \"real_time\": 6899076.237621754,\n            \"cpu_time\": 1082920.792079208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 51183699.99998625,\n            \"cpu_time\": 6510416.666666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1186,\n            \"real_time\": 592249.4097811138,\n            \"cpu_time\": 553330.5227655986,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 175,\n            \"real_time\": 4015842.8571417714,\n            \"cpu_time\": 3839285.714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31573409.090924546,\n            \"cpu_time\": 31960227.272727273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1257,\n            \"real_time\": 557404.2959427392,\n            \"cpu_time\": 509645.98249801114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 4001654.0697674933,\n            \"cpu_time\": 3997093.023255814,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_taskset_tree_bulk<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 32546909.52382502,\n            \"cpu_time\": 31994047.61904762,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kSmallSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 680,\n            \"real_time\": 1051290.000000068,\n            \"cpu_time\": 459558.82352941175,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kMediumSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 102,\n            \"real_time\": 6891887.254904063,\n            \"cpu_time\": 3063725.4901960786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_tree_when_all<kLargeSize>/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 51322991.66666598,\n            \"cpu_time\": 19531250.0,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:50:21-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"graph_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_taskflow_build_big_tree\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_build_big_tree\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 25833532.142866846,\n            \"cpu_time\": 25669642.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 5941274.999997859,\n            \"cpu_time\": 5859375.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_big_tree<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112,\n            \"real_time\": 7067700.892849059,\n            \"cpu_time\": 6975446.428571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_chain\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_chain\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4978,\n            \"real_time\": 136213.96143027165,\n            \"cpu_time\": 134968.86299718762,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_bi_prop_dependency_group\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_bi_prop_dependency_group\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 263529,\n            \"real_time\": 2581.249501953236,\n            \"cpu_time\": 2549.52965328294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24889,\n            \"real_time\": 28032.311462890517,\n            \"cpu_time\": 28250.431917714654,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_build_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24889,\n            \"real_time\": 28677.725099469477,\n            \"cpu_time\": 28878.219293663868,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56000,\n            \"real_time\": 12356.560714286908,\n            \"cpu_time\": 12276.785714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_execute_dependency_chain<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56000,\n            \"real_time\": 12459.033928572742,\n            \"cpu_time\": 12276.785714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::Graph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4592369.798608569,\n            \"cpu_time\": 4404362.416107383,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_forward_propagator_node<dispenso::BiPropGraph>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 149,\n            \"real_time\": 4386797.315437556,\n            \"cpu_time\": 4299496.644295302,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"graph_scene_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:50:34-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"graph_scene_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_parallel_for/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 28857943.478294108,\n            \"cpu_time\": 27853260.86956522,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_concurrent_task_set/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 11973226.415064791,\n            \"cpu_time\": 11497641.509433962,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_taskflow/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 18099464.864856087,\n            \"cpu_time\": 844594.5945945946,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_scene_graph_partial_revaluation/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1156,\n            \"real_time\": 601544.1176478347,\n            \"cpu_time\": 554173.875432526,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"idle_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:50:42-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"idle_pool_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6837,\n            \"real_time\": 108.8943249964334,\n            \"cpu_time\": 105.12651747842621,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9583,\n            \"real_time\": 69.1143796305345,\n            \"cpu_time\": 66.85015130961077,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8456,\n            \"real_time\": 82.3244678334926,\n            \"cpu_time\": 83.15101702932829,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9276,\n            \"real_time\": 85.62411599828017,\n            \"cpu_time\": 82.53827080638206,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10461,\n            \"real_time\": 67.20751362197133,\n            \"cpu_time\": 67.21393748207629,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9966,\n            \"real_time\": 69.92567730279316,\n            \"cpu_time\": 64.2810555890026,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6478,\n            \"real_time\": 104.24887310905096,\n            \"cpu_time\": 103.71642482247607,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_mostly_idle/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6394,\n            \"real_time\": 106.03587738499377,\n            \"cpu_time\": 102.63528307788552,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_mostly_idle/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4425,\n            \"real_time\": 156.75190960457957,\n            \"cpu_time\": 155.36723163841808,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_mostly_idle/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3745,\n            \"real_time\": 187.40803738333446,\n            \"cpu_time\": 187.75033377837116,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_mostly_idle/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1999,\n            \"real_time\": 363.61430715384876,\n            \"cpu_time\": 359.55477738869433,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_mostly_idle/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 503.2907000004343,\n            \"cpu_time\": 500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 705,\n            \"real_time\": 1000.6933333323826,\n            \"cpu_time\": 953.0141843971631,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 940,\n            \"real_time\": 620.2325531908269,\n            \"cpu_time\": 615.0265957446809,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1111,\n            \"real_time\": 636.8153915394709,\n            \"cpu_time\": 632.8757875787579,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1035,\n            \"real_time\": 673.0084057965098,\n            \"cpu_time\": 664.2512077294685,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1035,\n            \"real_time\": 668.5194202899753,\n            \"cpu_time\": 664.2512077294685,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 983,\n            \"real_time\": 714.8282807727232,\n            \"cpu_time\": 699.3896236012207,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 792,\n            \"real_time\": 969.1446969697214,\n            \"cpu_time\": 966.6982323232323,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb_mostly_idle/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 627,\n            \"real_time\": 945.3789473677593,\n            \"cpu_time\": 946.969696969697,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb_mostly_idle/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 491,\n            \"real_time\": 1489.867413442556,\n            \"cpu_time\": 1495.6720977596742,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb_mostly_idle/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 352,\n            \"real_time\": 2000.9383522728347,\n            \"cpu_time\": 1908.7357954545455,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb_mostly_idle/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212,\n            \"real_time\": 3367.8325471684284,\n            \"cpu_time\": 3390.330188679245,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb_mostly_idle/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 137,\n            \"real_time\": 4465.587591242509,\n            \"cpu_time\": 4219.890510948905,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 97064.52857140642,\n            \"cpu_time\": 95982.14285714286,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 60487.027272674,\n            \"cpu_time\": 61079.545454545456,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 81091.33333336003,\n            \"cpu_time\": 78125.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 67081.8818181777,\n            \"cpu_time\": 66761.36363636363,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 66798.31111109201,\n            \"cpu_time\": 64236.11111111111,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 81787.74444442954,\n            \"cpu_time\": 81597.22222222222,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 88620.65000005258,\n            \"cpu_time\": 87890.625,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/16/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb_mostly_idle/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 126471.58333326539,\n            \"cpu_time\": 122395.83333333333,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/24/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb_mostly_idle/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 140749.56000004022,\n            \"cpu_time\": 140625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/32/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb_mostly_idle/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 179141.89999987686,\n            \"cpu_time\": 171875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/48/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb_mostly_idle/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 342533.0000000031,\n            \"cpu_time\": 343750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_mostly_idle/64/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb_mostly_idle/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 473776.59999983734,\n            \"cpu_time\": 406250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/1/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109419.05000011805,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109621.98333330282,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/3/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110211.93333332728,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/4/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110327.7166666885,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/6/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110105.26666662675,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 110184.99999993634,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/12/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110196.56666667288,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/16/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb_very_idle/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109524.91666663869,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/24/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb_very_idle/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110043.38333335302,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb_very_idle/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109811.11666660581,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/48/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb_very_idle/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110293.11666667734,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb_very_idle/64/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb_very_idle/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 110031.40000002533,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85733,\n            \"real_time\": 8.091717308393113,\n            \"cpu_time\": 8.019082500320764,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92005,\n            \"real_time\": 7.865715993701925,\n            \"cpu_time\": 7.812075430683115,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 101385,\n            \"real_time\": 7.062882083147959,\n            \"cpu_time\": 6.9351975144252105,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35160,\n            \"real_time\": 23.93396188851053,\n            \"cpu_time\": 23.997440273037544,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 739.6942999994279,\n            \"cpu_time\": 734.375,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1084,\n            \"real_time\": 612.7190036897774,\n            \"cpu_time\": 619.8108856088561,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 928,\n            \"real_time\": 1178.2056034480224,\n            \"cpu_time\": 1161.7726293103449,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 493,\n            \"real_time\": 1309.8851926987982,\n            \"cpu_time\": 1299.4421906693713,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 486,\n            \"real_time\": 1296.4471193411969,\n            \"cpu_time\": 1253.858024691358,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 492,\n            \"real_time\": 1196.9085365851752,\n            \"cpu_time\": 1175.05081300813,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 534,\n            \"real_time\": 1688.3561797755071,\n            \"cpu_time\": 1638.5767790262173,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 461,\n            \"real_time\": 1514.9509761400375,\n            \"cpu_time\": 1525.2169197396963,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17440,\n            \"real_time\": 36.18218463303709,\n            \"cpu_time\": 34.941227064220186,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18423,\n            \"real_time\": 36.99201541547904,\n            \"cpu_time\": 36.46935895348206,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17408,\n            \"real_time\": 39.99319278492162,\n            \"cpu_time\": 37.69818474264706,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17401,\n            \"real_time\": 40.5917188667003,\n            \"cpu_time\": 40.40716050801678,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 739.9537000001146,\n            \"cpu_time\": 703.125,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 7024.2270000017015,\n            \"cpu_time\": 6718.75,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92,\n            \"real_time\": 12050.136956521903,\n            \"cpu_time\": 11888.58695652174,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 13561.712765952874,\n            \"cpu_time\": 12632.978723404256,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 13500.390384618953,\n            \"cpu_time\": 12920.673076923076,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 14603.163461533068,\n            \"cpu_time\": 13822.115384615385,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 14461.65434781901,\n            \"cpu_time\": 14605.978260869566,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 15286.295652181847,\n            \"cpu_time\": 14605.978260869566,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_mostly_idle/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 219,\n            \"real_time\": 3199.7547945205097,\n            \"cpu_time\": 3067.922374429224,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_mostly_idle/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 218,\n            \"real_time\": 3199.5041284379677,\n            \"cpu_time\": 3081.9954128440368,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_mostly_idle/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 218,\n            \"real_time\": 3391.3839449536295,\n            \"cpu_time\": 3368.6926605504586,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_mostly_idle/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 218,\n            \"real_time\": 3227.848623854188,\n            \"cpu_time\": 3225.3440366972477,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_mostly_idle/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 205,\n            \"real_time\": 4759.788292686586,\n            \"cpu_time\": 4496.951219512195,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_mostly_idle/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 62171.90172413932,\n            \"cpu_time\": 61961.206896551725,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_mostly_idle/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1307685.699999638,\n            \"cpu_time\": 1312500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/16/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_mostly_idle/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1238735.9000003925,\n            \"cpu_time\": 1234375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/24/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_mostly_idle/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1438651.7000002642,\n            \"cpu_time\": 1421875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/32/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_mostly_idle/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1432174.6999994502,\n            \"cpu_time\": 1437500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/48/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_mostly_idle/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1476455.6000000085,\n            \"cpu_time\": 1484375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_mostly_idle/64/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_mostly_idle/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1503446.4999998817,\n            \"cpu_time\": 1500000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_very_idle/1/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100577.44285716451,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_very_idle/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100477.97142864771,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_very_idle/3/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100540.0285714911,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_very_idle/4/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100614.27142863977,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_very_idle/6/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100561.41428568869,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_very_idle/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100445.54285715484,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_very_idle/12/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100716.21428583706,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/16/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_very_idle/16/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100619.41428570468,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/24/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_very_idle/24/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100809.07142855723,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_very_idle/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100698.04285714262,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/48/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_very_idle/48/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100645.08571420966,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_very_idle/64/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_very_idle/64/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100877.25714285106,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"locality_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:52:13-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"locality_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 407,\n            \"real_time\": 1785623.0958210195,\n            \"cpu_time\": 1765970.515970516,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 65261954.54551437,\n            \"cpu_time\": 65340909.09090909,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 537617699.9998279,\n            \"cpu_time\": 546875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 151,\n            \"real_time\": 4713486.754969339,\n            \"cpu_time\": 4759933.774834437,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 625,\n            \"real_time\": 1118057.2799989022,\n            \"cpu_time\": 1100000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1294,\n            \"real_time\": 509874.96136003983,\n            \"cpu_time\": 482998.4544049459,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1357,\n            \"real_time\": 513410.16949110146,\n            \"cpu_time\": 506632.27708179806,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/100000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1387,\n            \"real_time\": 509839.9423218571,\n            \"cpu_time\": 506939.43763518386,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 103735385.71418197,\n            \"cpu_time\": 102678571.42857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 20089636.842098307,\n            \"cpu_time\": 20148026.315789472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 6958756.122448718,\n            \"cpu_time\": 7015306.12244898,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 6393008.411221196,\n            \"cpu_time\": 6133177.570093458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/4000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 105,\n            \"real_time\": 6524390.476191738,\n            \"cpu_time\": 6547619.047619048,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 804808199.9995703,\n            \"cpu_time\": 796875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 145316299.99983126,\n            \"cpu_time\": 134375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 94043187.50000584,\n            \"cpu_time\": 87890625.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102488714.28575513,\n            \"cpu_time\": 95982142.85714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/128/32000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 102389357.14291334,\n            \"cpu_time\": 95982142.85714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 496,\n            \"real_time\": 1398130.0403227785,\n            \"cpu_time\": 1417590.7258064516,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1708,\n            \"real_time\": 640431.7915690942,\n            \"cpu_time\": 631220.7259953162,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2592,\n            \"real_time\": 257724.575617164,\n            \"cpu_time\": 259211.03395061727,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1841,\n            \"real_time\": 394259.36990761163,\n            \"cpu_time\": 398900.0543183053,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1001,\n            \"real_time\": 655733.5664337942,\n            \"cpu_time\": 452672.3276723277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 66101881.81821286,\n            \"cpu_time\": 66761363.63636363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17390972.500015777,\n            \"cpu_time\": 16796875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83,\n            \"real_time\": 7736593.975907058,\n            \"cpu_time\": 7718373.493975904,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 93,\n            \"real_time\": 7678023.655918428,\n            \"cpu_time\": 7728494.623655914,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 98,\n            \"real_time\": 6323190.816323292,\n            \"cpu_time\": 5420918.367346939,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 557717400.0000013,\n            \"cpu_time\": 562500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 217494299.99999848,\n            \"cpu_time\": 218750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 97710157.14289077,\n            \"cpu_time\": 89285714.28571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 104560383.33328857,\n            \"cpu_time\": 101562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 98818785.71429427,\n            \"cpu_time\": 35714285.71428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 503,\n            \"real_time\": 1372865.0099412487,\n            \"cpu_time\": 1366799.2047713718,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/4/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1422,\n            \"real_time\": 396449.9296767358,\n            \"cpu_time\": 395569.62025316455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/16/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2670,\n            \"real_time\": 287872.9962547995,\n            \"cpu_time\": 286750.936329588,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/64/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 983,\n            \"real_time\": 691375.1780263986,\n            \"cpu_time\": 635808.7487283825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/128/100000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 537,\n            \"real_time\": 1333293.4823094946,\n            \"cpu_time\": 1163873.370577281,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/1/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 68272969.99999817,\n            \"cpu_time\": 67187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/4/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41,\n            \"real_time\": 17701070.73171835,\n            \"cpu_time\": 17149390.243902437,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 97,\n            \"real_time\": 7704507.21649899,\n            \"cpu_time\": 7409793.81443299,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/64/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 6780490.00000101,\n            \"cpu_time\": 6093750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/128/4000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 90,\n            \"real_time\": 7062852.222225046,\n            \"cpu_time\": 7118055.555555556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/1/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 559581600.0004561,\n            \"cpu_time\": 562500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/4/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 174945149.999985,\n            \"cpu_time\": 171875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/16/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 105072962.50000308,\n            \"cpu_time\": 105468750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/64/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 123572514.28576481,\n            \"cpu_time\": 89285714.28571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/128/32000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 103039814.28569387,\n            \"cpu_time\": 98214285.71428572,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:53:08-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"nested_for_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 224000,\n            \"real_time\": 3286.5691964291595,\n            \"cpu_time\": 3208.7053571428573,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4073,\n            \"real_time\": 165775.9391111878,\n            \"cpu_time\": 161122.02307881168,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 747,\n            \"real_time\": 849949.6653277754,\n            \"cpu_time\": 857597.0548862115,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4777,\n            \"real_time\": 145914.33954359655,\n            \"cpu_time\": 147189.65878166212,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9054,\n            \"real_time\": 76030.04197040669,\n            \"cpu_time\": 75933.2891539651,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10413,\n            \"real_time\": 68772.11178339488,\n            \"cpu_time\": 69024.29655238644,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11565,\n            \"real_time\": 62312.82317343137,\n            \"cpu_time\": 60797.6653696498,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12983,\n            \"real_time\": 56159.78587382755,\n            \"cpu_time\": 56564.353385196024,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13632,\n            \"real_time\": 51719.34419020101,\n            \"cpu_time\": 51579.005281690144,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14803,\n            \"real_time\": 48535.97243800427,\n            \"cpu_time\": 47498.817807201245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15811,\n            \"real_time\": 44645.04458926293,\n            \"cpu_time\": 44470.621719056355,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15860,\n            \"real_time\": 44210.11349302964,\n            \"cpu_time\": 44333.228247162675,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16219,\n            \"real_time\": 43529.391454463344,\n            \"cpu_time\": 43351.93291818238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14124,\n            \"real_time\": 48519.50580573356,\n            \"cpu_time\": 48676.01246105919,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19527,\n            \"real_time\": 36625.71311519222,\n            \"cpu_time\": 36007.83530496236,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 228494533.33340836,\n            \"cpu_time\": 223958333.33333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 74110944.44453031,\n            \"cpu_time\": 74652777.77777778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 50489110.000035,\n            \"cpu_time\": 51562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19,\n            \"real_time\": 35876015.789462574,\n            \"cpu_time\": 36184210.526315786,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 23832541.37930635,\n            \"cpu_time\": 22629310.344827585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 18014897.36843857,\n            \"cpu_time\": 17680921.05263158,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 11929637.50000737,\n            \"cpu_time\": 11997767.857142856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 74,\n            \"real_time\": 8773572.972979702,\n            \"cpu_time\": 8657094.594594594,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108,\n            \"real_time\": 6543461.111117789,\n            \"cpu_time\": 6365740.740740741,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 119,\n            \"real_time\": 4916952.941176005,\n            \"cpu_time\": 4989495.798319328,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 164,\n            \"real_time\": 4261844.512196083,\n            \"cpu_time\": 4287347.560975609,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 4260097.093022121,\n            \"cpu_time\": 4269622.0930232555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4153688699.999293,\n            \"cpu_time\": 4140625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1577121799.9999862,\n            \"cpu_time\": 1562500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 999466399.9996191,\n            \"cpu_time\": 1000000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 751229499.9996811,\n            \"cpu_time\": 750000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 500239400.00028235,\n            \"cpu_time\": 500000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 375621350.000074,\n            \"cpu_time\": 367187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 252477166.66672206,\n            \"cpu_time\": 250000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 190841374.99999088,\n            \"cpu_time\": 191406250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 126194860.00003235,\n            \"cpu_time\": 125000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 114451433.3332154,\n            \"cpu_time\": 114583333.33333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 78378177.77787374,\n            \"cpu_time\": 78125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/2500/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 65656236.363627784,\n            \"cpu_time\": 66761363.63636363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20659,\n            \"real_time\": 33858.357132509685,\n            \"cpu_time\": 33278.47427271407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32581,\n            \"real_time\": 21570.053098417982,\n            \"cpu_time\": 21580.8293177005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39131,\n            \"real_time\": 17931.951649596445,\n            \"cpu_time\": 17968.49045513787,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46350,\n            \"real_time\": 15031.24703342606,\n            \"cpu_time\": 14832.793959007551,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54394,\n            \"real_time\": 12856.704783621133,\n            \"cpu_time\": 12926.517630621025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52849,\n            \"real_time\": 13217.631364842755,\n            \"cpu_time\": 13304.414463849836,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50863,\n            \"real_time\": 13752.40154925209,\n            \"cpu_time\": 13823.899494721114,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50129,\n            \"real_time\": 14158.554928287698,\n            \"cpu_time\": 14026.31211474396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42674,\n            \"real_time\": 16291.79828467407,\n            \"cpu_time\": 16110.512255706051,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36424,\n            \"real_time\": 19550.381616508203,\n            \"cpu_time\": 19732.86843839227,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32965,\n            \"real_time\": 23404.35310177283,\n            \"cpu_time\": 23699.378128317912,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 30321,\n            \"real_time\": 23205.286764936332,\n            \"cpu_time\": 23189.373701395074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 98900542.85707654,\n            \"cpu_time\": 95982142.85714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 49213564.28576474,\n            \"cpu_time\": 49107142.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 32481114.285734035,\n            \"cpu_time\": 32738095.23809524,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 24127933.333349776,\n            \"cpu_time\": 24305555.555555556,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 15949166.66666298,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 11932260.71429113,\n            \"cpu_time\": 11997767.857142856,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81,\n            \"real_time\": 7684871.604935864,\n            \"cpu_time\": 7716049.382716049,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 107,\n            \"real_time\": 6136046.728974281,\n            \"cpu_time\": 6133177.570093458,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 5355518.571429586,\n            \"cpu_time\": 5357142.857142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5103538.000003028,\n            \"cpu_time\": 5156250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 194,\n            \"real_time\": 3856418.0412341207,\n            \"cpu_time\": 3704896.907216495,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 193,\n            \"real_time\": 3519849.740934066,\n            \"cpu_time\": 3562176.165803109,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2559967000.0001426,\n            \"cpu_time\": 2500000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1282695899.999453,\n            \"cpu_time\": 1265625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 863696499.9996053,\n            \"cpu_time\": 859375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 661091900.0004287,\n            \"cpu_time\": 656250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 435640500.0003179,\n            \"cpu_time\": 437500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 326697049.99989337,\n            \"cpu_time\": 328125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 217506166.66668066,\n            \"cpu_time\": 218750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 164267100.0001883,\n            \"cpu_time\": 164062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 121834599.99996558,\n            \"cpu_time\": 121875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 95636900.00004499,\n            \"cpu_time\": 95703125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 70992060.00002596,\n            \"cpu_time\": 70312500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/2500/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 60689918.18185829,\n            \"cpu_time\": 59659090.90909091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto/1/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20784,\n            \"real_time\": 33687.88972284375,\n            \"cpu_time\": 33830.109699769055,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto/2/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36000,\n            \"real_time\": 19424.450000011955,\n            \"cpu_time\": 19531.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto/3/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37558,\n            \"real_time\": 18663.15831513799,\n            \"cpu_time\": 18721.044784067308,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto/4/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 41761,\n            \"real_time\": 16755.180670978563,\n            \"cpu_time\": 16836.881300735135,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto/6/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50145,\n            \"real_time\": 13995.752318279374,\n            \"cpu_time\": 14021.836673646425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto/8/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47996,\n            \"real_time\": 14570.145428787277,\n            \"cpu_time\": 14649.658304858738,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto/12/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47869,\n            \"real_time\": 14634.111846913034,\n            \"cpu_time\": 14688.524932628632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto/16/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46408,\n            \"real_time\": 15070.533097749054,\n            \"cpu_time\": 14814.256162730564,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto/24/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 39652,\n            \"real_time\": 17532.777665676273,\n            \"cpu_time\": 16944.29032583476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto/32/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27787,\n            \"real_time\": 24044.938280494644,\n            \"cpu_time\": 24179.47241515817,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto/48/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27562,\n            \"real_time\": 25295.323271181638,\n            \"cpu_time\": 25510.6668601698,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/10/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto/64/10/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25228,\n            \"real_time\": 27873.747423523204,\n            \"cpu_time\": 27870.818138576185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto/1/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 98946399.99999656,\n            \"cpu_time\": 93750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto/2/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 50230000.00002347,\n            \"cpu_time\": 50223214.28571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto/3/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33007485.714300685,\n            \"cpu_time\": 31994047.61904762,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto/4/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 24616053.57143526,\n            \"cpu_time\": 23995535.714285713,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto/6/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 15922557.14285784,\n            \"cpu_time\": 15997023.80952381,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto/8/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 11890414.814809414,\n            \"cpu_time\": 11574074.074074075,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto/12/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 7494749.999999667,\n            \"cpu_time\": 7440476.19047619,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto/16/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 110,\n            \"real_time\": 5577084.545455529,\n            \"cpu_time\": 5539772.7272727275,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto/24/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 178,\n            \"real_time\": 3806923.595501747,\n            \"cpu_time\": 3774578.6516853934,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_auto/32/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 207,\n            \"real_time\": 3205513.526571792,\n            \"cpu_time\": 3170289.855072464,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_auto/48/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 231,\n            \"real_time\": 3221090.909088768,\n            \"cpu_time\": 3111471.8614718616,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_auto/64/500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 244,\n            \"real_time\": 3018158.196721101,\n            \"cpu_time\": 2881659.8360655736,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_auto/1/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2616940200.0004992,\n            \"cpu_time\": 2578125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_auto/2/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1296681300.000273,\n            \"cpu_time\": 1281250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_auto/3/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 900569599.9994714,\n            \"cpu_time\": 890625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_auto/4/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 655600399.9994572,\n            \"cpu_time\": 656250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_auto/6/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 443145550.0002812,\n            \"cpu_time\": 445312500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_auto/8/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 328264000.0002175,\n            \"cpu_time\": 328125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_auto/12/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 215561666.66687202,\n            \"cpu_time\": 213541666.66666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/16/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_auto/16/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 164372725.0000211,\n            \"cpu_time\": 160156250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/24/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_auto/24/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 109581100.00001396,\n            \"cpu_time\": 109375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/32/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_auto/32/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 84895275.00000805,\n            \"cpu_time\": 83984375.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/48/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_auto/48/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 66725381.81820445,\n            \"cpu_time\": 65340909.09090909,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto/64/2500/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_auto/64/2500/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12,\n            \"real_time\": 56781658.33334485,\n            \"cpu_time\": 55989583.333333336,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"nested_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:54:59-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"nested_pool_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 168,\n            \"real_time\": 3892.6750000016564,\n            \"cpu_time\": 3813.2440476190477,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 278,\n            \"real_time\": 2550.5402877701167,\n            \"cpu_time\": 2473.021582733813,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 277,\n            \"real_time\": 2543.303610107594,\n            \"cpu_time\": 2481.9494584837544,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 341,\n            \"real_time\": 2005.9129032249616,\n            \"cpu_time\": 2016.1290322580646,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 370,\n            \"real_time\": 2024.781081080299,\n            \"cpu_time\": 1942.5675675675675,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 373,\n            \"real_time\": 1893.734584448601,\n            \"cpu_time\": 1885.053619302949,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 397,\n            \"real_time\": 1753.516120907744,\n            \"cpu_time\": 1731.7380352644836,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 442,\n            \"real_time\": 1575.6957013578703,\n            \"cpu_time\": 1590.7805429864254,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 469,\n            \"real_time\": 1474.6793176973738,\n            \"cpu_time\": 1432.5692963752665,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 493,\n            \"real_time\": 1450.199188640012,\n            \"cpu_time\": 1457.9107505070995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 536,\n            \"real_time\": 1304.199626864924,\n            \"cpu_time\": 1311.8003731343283,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 512,\n            \"real_time\": 1382.9853515634481,\n            \"cpu_time\": 1373.291015625,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 105959.16666655587,\n            \"cpu_time\": 104166.66666666667,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 54654.66923082064,\n            \"cpu_time\": 55288.46153846154,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13,\n            \"real_time\": 52332.97692302586,\n            \"cpu_time\": 52884.61538461538,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 49357.07142859818,\n            \"cpu_time\": 49107.142857142855,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41991.029411773896,\n            \"cpu_time\": 41360.294117647056,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20,\n            \"real_time\": 35743.05500001174,\n            \"cpu_time\": 35937.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 30247.943478254612,\n            \"cpu_time\": 30570.652173913044,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24344.693103432353,\n            \"cpu_time\": 24245.689655172413,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 20412.067647050528,\n            \"cpu_time\": 20220.58823529412,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 19978.605882362684,\n            \"cpu_time\": 19761.029411764706,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17486.680000001797,\n            \"cpu_time\": 17578.125,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40,\n            \"real_time\": 17482.43750000711,\n            \"cpu_time\": 17187.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 18044294.700000137,\n            \"cpu_time\": 17921875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7065072.499999587,\n            \"cpu_time\": 7000000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5501108.999999815,\n            \"cpu_time\": 5500000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4483277.099999214,\n            \"cpu_time\": 4468750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3272344.9000004623,\n            \"cpu_time\": 3281250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2602393.4999993797,\n            \"cpu_time\": 2546875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1837074.6999999029,\n            \"cpu_time\": 1781250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1465866.3999998681,\n            \"cpu_time\": 1453125.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1134443.299999475,\n            \"cpu_time\": 1109375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1034357.9000000318,\n            \"cpu_time\": 1046875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 910747.8999994782,\n            \"cpu_time\": 906250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/300000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 940844.6999996158,\n            \"cpu_time\": 937500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 805,\n            \"real_time\": 863.2724223609545,\n            \"cpu_time\": 834.6273291925465,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 556,\n            \"real_time\": 1199.5239208628598,\n            \"cpu_time\": 1208.408273381295,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 613,\n            \"real_time\": 1150.5110929858026,\n            \"cpu_time\": 1045.0652528548123,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 823,\n            \"real_time\": 875.495139733226,\n            \"cpu_time\": 873.329283110571,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 832,\n            \"real_time\": 905.1462740381147,\n            \"cpu_time\": 901.4423076923077,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 814,\n            \"real_time\": 943.8653562656708,\n            \"cpu_time\": 959.7665847665847,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 682,\n            \"real_time\": 1176.5151026389249,\n            \"cpu_time\": 1145.5278592375366,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 688,\n            \"real_time\": 1117.1101744176392,\n            \"cpu_time\": 1112.827034883721,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 437,\n            \"real_time\": 1574.7970251713277,\n            \"cpu_time\": 1537.4713958810069,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 380,\n            \"real_time\": 1899.4592105268807,\n            \"cpu_time\": 1809.2105263157894,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 313,\n            \"real_time\": 2047.8376996811166,\n            \"cpu_time\": 1996.8051118210863,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 248,\n            \"real_time\": 2754.6197580638745,\n            \"cpu_time\": 2772.1774193548385,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 24995.22500001409,\n            \"cpu_time\": 25111.60714285714,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 20401.8171428418,\n            \"cpu_time\": 20089.285714285714,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21819.796874979147,\n            \"cpu_time\": 21484.375,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 16063.281081064692,\n            \"cpu_time\": 15202.702702702703,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 18918.259183678576,\n            \"cpu_time\": 18813.775510204083,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61,\n            \"real_time\": 11774.160655730782,\n            \"cpu_time\": 11526.639344262296,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 79,\n            \"real_time\": 11747.431645571965,\n            \"cpu_time\": 11669.303797468354,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57,\n            \"real_time\": 11700.133333330374,\n            \"cpu_time\": 10964.912280701754,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 21380.447826073658,\n            \"cpu_time\": 20380.434782608696,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 27,\n            \"real_time\": 25750.955555546778,\n            \"cpu_time\": 24884.25925925926,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26,\n            \"real_time\": 26381.953846164553,\n            \"cpu_time\": 26442.30769230769,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 28146.021428580883,\n            \"cpu_time\": 28459.821428571428,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4031846.300000325,\n            \"cpu_time\": 4000000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 728813.4000000355,\n            \"cpu_time\": 718750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 889849.3000006056,\n            \"cpu_time\": 890625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 994105.6999996363,\n            \"cpu_time\": 968750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1049320.0000000796,\n            \"cpu_time\": 1046875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1522894.499999893,\n            \"cpu_time\": 1484375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 997350.8000002766,\n            \"cpu_time\": 968750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1162328.2000000472,\n            \"cpu_time\": 1140625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 719202.5000003923,\n            \"cpu_time\": 703125.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 590710.8999999764,\n            \"cpu_time\": 593750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 538416.5999994366,\n            \"cpu_time\": 531250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/300000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 389333.69999995193,\n            \"cpu_time\": 375000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2933,\n            \"real_time\": 239.12471871795694,\n            \"cpu_time\": 234.4016365496079,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 672,\n            \"real_time\": 993.2983630941786,\n            \"cpu_time\": 976.5625,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 872,\n            \"real_time\": 734.3979357791786,\n            \"cpu_time\": 734.6616972477065,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2240,\n            \"real_time\": 347.99933035734347,\n            \"cpu_time\": 348.77232142857144,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1754,\n            \"real_time\": 431.1715507410948,\n            \"cpu_time\": 427.594070695553,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2964,\n            \"real_time\": 233.20158569493464,\n            \"cpu_time\": 221.4068825910931,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1831,\n            \"real_time\": 487.40065537951824,\n            \"cpu_time\": 486.4145275805571,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1980,\n            \"real_time\": 296.3487878787418,\n            \"cpu_time\": 299.87373737373736,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1557,\n            \"real_time\": 493.6928066792973,\n            \"cpu_time\": 451.5895953757225,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1376,\n            \"real_time\": 509.50043604641087,\n            \"cpu_time\": 476.92587209302326,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1704,\n            \"real_time\": 396.0932511737869,\n            \"cpu_time\": 394.2928403755869,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2008,\n            \"real_time\": 426.3131474107398,\n            \"cpu_time\": 404.6314741035857,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 104,\n            \"real_time\": 6700.27788461224,\n            \"cpu_time\": 6760.817307692308,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 7865.334090907213,\n            \"cpu_time\": 7634.943181818182,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 108,\n            \"real_time\": 6414.663888891583,\n            \"cpu_time\": 6365.740740740741,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 88,\n            \"real_time\": 8359.228409093786,\n            \"cpu_time\": 7102.272727272727,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 4203.702840909914,\n            \"cpu_time\": 4083.806818181818,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 183,\n            \"real_time\": 3326.603825132865,\n            \"cpu_time\": 3329.9180327868853,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 197,\n            \"real_time\": 4188.728934012236,\n            \"cpu_time\": 4203.680203045686,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 347,\n            \"real_time\": 2857.99221901916,\n            \"cpu_time\": 2836.815561959654,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 179,\n            \"real_time\": 3676.2754189925413,\n            \"cpu_time\": 3491.6201117318437,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 203,\n            \"real_time\": 3729.014285714324,\n            \"cpu_time\": 3771.551724137931,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 3748.9309859179034,\n            \"cpu_time\": 3741.1971830985917,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 216,\n            \"real_time\": 3348.57685185044,\n            \"cpu_time\": 3327.546296296296,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_bulk/1/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1021553.2000001986,\n            \"cpu_time\": 1015625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_bulk/2/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 550953.599999957,\n            \"cpu_time\": 546875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_bulk/3/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 808491.700000559,\n            \"cpu_time\": 781250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_bulk/4/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 575432.6000005676,\n            \"cpu_time\": 562500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_bulk/6/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 428497.8999999112,\n            \"cpu_time\": 421875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_bulk/8/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 301521.5999998873,\n            \"cpu_time\": 281250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_bulk/12/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 271191.1500000497,\n            \"cpu_time\": 265625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_bulk/16/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 184467.9000000724,\n            \"cpu_time\": 183593.75,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_bulk/24/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 160944.57500003045,\n            \"cpu_time\": 160156.25,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_bulk/32/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 123093.80000003027,\n            \"cpu_time\": 122395.83333333333,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_bulk/48/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 101482.81428571083,\n            \"cpu_time\": 100446.42857142857,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/300000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_bulk/64/300000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 94858.25000001569,\n            \"cpu_time\": 93750.0,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"once_function_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:57:26-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"once_function_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_move_std_function<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8960000,\n            \"real_time\": 84.60370535721447,\n            \"cpu_time\": 85.44921875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kSmallSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56000000,\n            \"real_time\": 13.297325000004482,\n            \"cpu_time\": 13.392857142857142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kMediumSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7466667,\n            \"real_time\": 87.93886214566874,\n            \"cpu_time\": 85.79798724116128,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kMediumSize>\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64000000,\n            \"real_time\": 12.44779218750125,\n            \"cpu_time\": 12.20703125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kLargeSize>\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8960000,\n            \"real_time\": 85.50149553577009,\n            \"cpu_time\": 85.44921875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kLargeSize>\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44800000,\n            \"real_time\": 15.474499999998313,\n            \"cpu_time\": 15.694754464285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6400000,\n            \"real_time\": 99.84706250008912,\n            \"cpu_time\": 100.09765625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_move_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11200000,\n            \"real_time\": 63.17638392853756,\n            \"cpu_time\": 64.17410714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 407273,\n            \"real_time\": 1728.3028828328033,\n            \"cpu_time\": 1726.4218349853784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kSmallSize>\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44800,\n            \"real_time\": 15993.8772321563,\n            \"cpu_time\": 16043.526785714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kSmallSize>\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 165926,\n            \"real_time\": 4151.649530510759,\n            \"cpu_time\": 4143.413328833335,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 298667,\n            \"real_time\": 2298.9828136373135,\n            \"cpu_time\": 2301.8947523496067,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kMediumSize>\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44800,\n            \"real_time\": 15449.176339278178,\n            \"cpu_time\": 14997.20982142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kMediumSize>\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154483,\n            \"real_time\": 4444.022319605726,\n            \"cpu_time\": 4450.327867791278,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 179200,\n            \"real_time\": 4106.250000001564,\n            \"cpu_time\": 4098.074776785715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kLargeSize>\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 40727,\n            \"real_time\": 16863.257789670104,\n            \"cpu_time\": 16880.69339750043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kLargeSize>\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 112000,\n            \"real_time\": 5714.958035712568,\n            \"cpu_time\": 5719.866071428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_inline_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56000,\n            \"real_time\": 11814.530357144447,\n            \"cpu_time\": 11718.75,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_std_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24977,\n            \"real_time\": 27332.48588702272,\n            \"cpu_time\": 27525.32329743364,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_queue_once_function<kExtraLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24889,\n            \"real_time\": 24791.373699199172,\n            \"cpu_time\": 24483.707662019366,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pipeline_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:57:47-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"pipeline_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 517309400.00015837,\n            \"cpu_time\": 515625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 323648450.00029165,\n            \"cpu_time\": 125000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 345052449.9999119,\n            \"cpu_time\": 296875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 279032433.33336526,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_par/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 17289443.24325287,\n            \"cpu_time\": 2956081.081081081,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb_par/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 15333088.888898298,\n            \"cpu_time\": 14583333.333333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow_par/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow_par/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 177765800.00008833,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"pool_allocator_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T08:57:56-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"pool_allocator_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 145,\n            \"real_time\": 4841874.482754692,\n            \"cpu_time\": 4849137.931034483,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 20133108.82351588,\n            \"cpu_time\": 20220588.23529412,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 151697.4553571312,\n            \"cpu_time\": 153459.82142857142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 608897.767857083,\n            \"cpu_time\": 613839.2857142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19478,\n            \"real_time\": 36529.972276425644,\n            \"cpu_time\": 36900.605811684974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 149938.8169644281,\n            \"cpu_time\": 149972.0982142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 15900661.76469704,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 86727966.66678551,\n            \"cpu_time\": 88541666.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 151710.62499998047,\n            \"cpu_time\": 149972.0982142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 610194.3750000568,\n            \"cpu_time\": 613839.2857142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20364,\n            \"real_time\": 34454.390100169076,\n            \"cpu_time\": 34527.84325279906,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4978,\n            \"real_time\": 137750.74327024948,\n            \"cpu_time\": 131830.05222981118,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 52209740.000034794,\n            \"cpu_time\": 51562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 338507800.0001158,\n            \"cpu_time\": 335937500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 151843.12499993018,\n            \"cpu_time\": 149972.0982142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 613170.6473218352,\n            \"cpu_time\": 610351.5625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 18667,\n            \"real_time\": 36677.227192370396,\n            \"cpu_time\": 36829.699469652325,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 148020.87053575568,\n            \"cpu_time\": 146484.375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7467,\n            \"real_time\": 87785.24173030464,\n            \"cpu_time\": 87886.70148654078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2036,\n            \"real_time\": 354860.6581531803,\n            \"cpu_time\": 360694.9901768173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17920,\n            \"real_time\": 38532.90736606547,\n            \"cpu_time\": 38364.955357142855,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4978,\n            \"real_time\": 153872.82040979038,\n            \"cpu_time\": 153801.72760144636,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7467,\n            \"real_time\": 87807.96839426439,\n            \"cpu_time\": 85794.16097495648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2036,\n            \"real_time\": 369143.4184678627,\n            \"cpu_time\": 360694.9901768173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14933,\n            \"real_time\": 42947.78008440383,\n            \"cpu_time\": 39760.932163664365,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3446,\n            \"real_time\": 163558.2704584923,\n            \"cpu_time\": 158698.49100406267,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5600,\n            \"real_time\": 102888.89285707878,\n            \"cpu_time\": 97656.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1673,\n            \"real_time\": 396455.46921698225,\n            \"cpu_time\": 382919.904363419,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15448,\n            \"real_time\": 38635.22138789477,\n            \"cpu_time\": 39446.85396167789,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_nl_pool_allocator_arena<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 182755.6250000433,\n            \"cpu_time\": 177873.88392857142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 560,\n            \"real_time\": 1282449.9999997637,\n            \"cpu_time\": 1171875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 179,\n            \"real_time\": 5457345.251396258,\n            \"cpu_time\": 5062849.162011174,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 740431.6964287513,\n            \"cpu_time\": 725446.4285714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"family_index\": 16,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2283438.6363614835,\n            \"cpu_time\": 2249053.0303030303,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 4142546.250000123,\n            \"cpu_time\": 4199218.75,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 17,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 134987949.99986786,\n            \"cpu_time\": 85937500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 617903.2142857263,\n            \"cpu_time\": 613839.2857142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"family_index\": 18,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 299,\n            \"real_time\": 2138911.7056853967,\n            \"cpu_time\": 2142558.5284280935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 361473675.0000702,\n            \"cpu_time\": 242187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 19,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1761543900.000106,\n            \"cpu_time\": 1093750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 632641.183035584,\n            \"cpu_time\": 610351.5625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"family_index\": 20,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,2>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2622329.166666587,\n            \"cpu_time\": 2604166.6666666665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 213,\n            \"real_time\": 4267534.7417848725,\n            \"cpu_time\": 3301056.3380281692,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 21,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 37,\n            \"real_time\": 43508459.459460296,\n            \"cpu_time\": 19425675.675675675,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 28401976.00002284,\n            \"cpu_time\": 28750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"family_index\": 22,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 119940283.33341096,\n            \"cpu_time\": 119791666.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 157427864.7058771,\n            \"cpu_time\": 54227941.176470585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 23,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 1071541200.0004108,\n            \"cpu_time\": 289062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 24,\n            \"real_time\": 28545066.66665202,\n            \"cpu_time\": 27994791.666666668,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"family_index\": 24,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 125883900.00000799,\n            \"cpu_time\": 125000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2990842500.000326,\n            \"cpu_time\": 1203125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 25,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 29085644200.00039,\n            \"cpu_time\": 6484375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 30857290.476195063,\n            \"cpu_time\": 30505952.38095238,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"family_index\": 26,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,8>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 148626225.00004363,\n            \"cpu_time\": 148437500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 29071062.000002712,\n            \"cpu_time\": 13125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 27,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 315045845.45448536,\n            \"cpu_time\": 116477272.72727273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 147053179.99996623,\n            \"cpu_time\": 146875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"family_index\": 28,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kSmallSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 575132300.000405,\n            \"cpu_time\": 546875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 1089591550.000023,\n            \"cpu_time\": 206250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 29,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 6414324400.000624,\n            \"cpu_time\": 3578125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 139295816.66676918,\n            \"cpu_time\": 138020833.33333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"family_index\": 30,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kMediumSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 614732399.9994115,\n            \"cpu_time\": 609375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 20524383299.9995,\n            \"cpu_time\": 2375000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 31,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_mallocfree_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 126245421600.00055,\n            \"cpu_time\": 20328125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 143203459.99985877,\n            \"cpu_time\": 143750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"family_index\": 32,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_pool_allocator_threaded<kLargeSize,16>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 868872099.9998623,\n            \"cpu_time\": 859375000.0,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"rw_lock_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:02:27-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"rw_lock_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<NopMutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 620,\n            \"real_time\": 1117013.8709677567,\n            \"cpu_time\": 1108870.9677419355,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<NopMutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 933,\n            \"real_time\": 751688.8531617045,\n            \"cpu_time\": 753617.3633440514,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<NopMutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1002,\n            \"real_time\": 696887.0259483511,\n            \"cpu_time\": 686127.744510978,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<NopMutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 935,\n            \"real_time\": 743824.0641708043,\n            \"cpu_time\": 735294.1176470588,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<NopMutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1017,\n            \"real_time\": 691569.5181911967,\n            \"cpu_time\": 676007.866273353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<std::shared_mutex>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19305188.888867836,\n            \"cpu_time\": 19097222.222222224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<std::shared_mutex>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19369341.666662067,\n            \"cpu_time\": 19097222.222222224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<std::shared_mutex>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19416355.55555068,\n            \"cpu_time\": 19097222.222222224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<std::shared_mutex>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19409374.999996647,\n            \"cpu_time\": 19097222.222222224,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<std::shared_mutex>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 19450205.55556059,\n            \"cpu_time\": 19531250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 16413025.58138789,\n            \"cpu_time\": 15988372.093023255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 15095457.446806634,\n            \"cpu_time\": 15292553.191489361,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 14557727.083342798,\n            \"cpu_time\": 14322916.666666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14445100.000000598,\n            \"cpu_time\": 14030612.24489796,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_serial<dispenso::RWLock>/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14355700.000012396,\n            \"cpu_time\": 14349489.795918368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 35,\n            \"real_time\": 19930965.714281358,\n            \"cpu_time\": 19642857.14285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 60408490.000008896,\n            \"cpu_time\": 59375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 337606033.3333347,\n            \"cpu_time\": 333333333.3333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1040186500.0003453,\n            \"cpu_time\": 984375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2435386000.000108,\n            \"cpu_time\": 2296875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/2/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5883264100.000815,\n            \"cpu_time\": 4656250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 36,\n            \"real_time\": 21549513.888885483,\n            \"cpu_time\": 21267361.111111112,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 75667622.22217625,\n            \"cpu_time\": 74652777.77777778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 314955900.0003137,\n            \"cpu_time\": 312500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1079131499.9996758,\n            \"cpu_time\": 1078125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2836406999.999781,\n            \"cpu_time\": 2765625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/8/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 6595037799.999773,\n            \"cpu_time\": 5468750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 21245997.058833703,\n            \"cpu_time\": 21139705.88235294,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 72240179.9999716,\n            \"cpu_time\": 71875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 317916500.0001376,\n            \"cpu_time\": 312500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 996513100.0008113,\n            \"cpu_time\": 1000000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2575993400.000698,\n            \"cpu_time\": 2312500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/32/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 6022973900.000579,\n            \"cpu_time\": 4453125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 20044875.7575831,\n            \"cpu_time\": 20359848.484848484,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 74689120.00003912,\n            \"cpu_time\": 73437500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 339969900.0001419,\n            \"cpu_time\": 335937500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 889150599.9999936,\n            \"cpu_time\": 890625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2100237499.999821,\n            \"cpu_time\": 2062500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/128/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 5162757999.999485,\n            \"cpu_time\": 5140625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 21410923.52940177,\n            \"cpu_time\": 20680147.05882353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 77721177.77777667,\n            \"cpu_time\": 78125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 346075800.0001078,\n            \"cpu_time\": 328125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 910926999.9999014,\n            \"cpu_time\": 906250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/16/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/16/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1920998399.9999168,\n            \"cpu_time\": 1750000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<std::shared_mutex>/32/512/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_parallel<std::shared_mutex>/32/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4707656599.999609,\n            \"cpu_time\": 4671875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 16511460.465111203,\n            \"cpu_time\": 16351744.186046511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 123026942.85712537,\n            \"cpu_time\": 122767857.14285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 651270000.0002952,\n            \"cpu_time\": 625000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2099785399.999746,\n            \"cpu_time\": 2093750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 12183545500.000036,\n            \"cpu_time\": 12109375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/2/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/2/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 47369681199.99983,\n            \"cpu_time\": 46890625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 15019802.127658585,\n            \"cpu_time\": 14627659.574468086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 89142955.55556843,\n            \"cpu_time\": 88541666.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 365472749.9997534,\n            \"cpu_time\": 359375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1228708399.9999595,\n            \"cpu_time\": 1203125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4374994499.999957,\n            \"cpu_time\": 4328125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/8/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/8/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 20147908899.999493,\n            \"cpu_time\": 19953125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 15939482.222226312,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 73564466.66674149,\n            \"cpu_time\": 72916666.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 281179333.33336014,\n            \"cpu_time\": 281250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 593563399.9997662,\n            \"cpu_time\": 578125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2002235500.000097,\n            \"cpu_time\": 1984375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/32/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/32/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7846040399.999765,\n            \"cpu_time\": 7843750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14741991.836727927,\n            \"cpu_time\": 14668367.346938776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 65577990.000019774,\n            \"cpu_time\": 65625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 168589574.99994177,\n            \"cpu_time\": 164062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 417482050.00021696,\n            \"cpu_time\": 421875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1275850800.0006258,\n            \"cpu_time\": 1265625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/128/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/128/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3649717499.999497,\n            \"cpu_time\": 3640625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/1/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14390197.959166508,\n            \"cpu_time\": 14349489.795918368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/2/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 59954890.90913577,\n            \"cpu_time\": 59659090.90909091,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/4/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 155646274.99998096,\n            \"cpu_time\": 156250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/8/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 373191650.0000807,\n            \"cpu_time\": 359375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/16/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/16/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 859905499.9995133,\n            \"cpu_time\": 843750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_parallel<dispenso::RWLock>/32/512/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_parallel<dispenso::RWLock>/32/512/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2162233600.000036,\n            \"cpu_time\": 2125000000.0,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:05:42-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"simple_for_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5600000,\n            \"real_time\": 123.07973214287163,\n            \"cpu_time\": 119.97767857142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2133,\n            \"real_time\": 319111.9549932008,\n            \"cpu_time\": 322315.9868729489,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 67764627.2727295,\n            \"cpu_time\": 63920454.54545455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7638,\n            \"real_time\": 94489.09400372862,\n            \"cpu_time\": 94101.8591254255,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12668,\n            \"real_time\": 55404.19955797613,\n            \"cpu_time\": 55504.02589201137,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13726,\n            \"real_time\": 52165.437855183314,\n            \"cpu_time\": 52364.12647530234,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14206,\n            \"real_time\": 49971.01224834739,\n            \"cpu_time\": 49494.931718991975,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15840,\n            \"real_time\": 45114.74747472575,\n            \"cpu_time\": 45375.631313131315,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16035,\n            \"real_time\": 44121.334580600385,\n            \"cpu_time\": 44823.82288743374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16553,\n            \"real_time\": 42392.62973476715,\n            \"cpu_time\": 42477.19446625989,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17287,\n            \"real_time\": 40821.44385952365,\n            \"cpu_time\": 41577.48597211778,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17682,\n            \"real_time\": 38385.39192397927,\n            \"cpu_time\": 37997.68125777627,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17828,\n            \"real_time\": 38079.58828807129,\n            \"cpu_time\": 38562.93470944581,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16360,\n            \"real_time\": 43669.55378971126,\n            \"cpu_time\": 43933.37408312959,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22205,\n            \"real_time\": 31402.742625543535,\n            \"cpu_time\": 30961.49515874803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 302,\n            \"real_time\": 2301049.999998864,\n            \"cpu_time\": 2276490.0662251655,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 955,\n            \"real_time\": 732378.3246071336,\n            \"cpu_time\": 736256.5445026178,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1293,\n            \"real_time\": 552477.5715394203,\n            \"cpu_time\": 543793.5034802784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1661,\n            \"real_time\": 418109.99397952174,\n            \"cpu_time\": 423314.268512944,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2319,\n            \"real_time\": 314212.67787841236,\n            \"cpu_time\": 316677.4471755067,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2881,\n            \"real_time\": 251644.77611938928,\n            \"cpu_time\": 249479.3474488025,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3736,\n            \"real_time\": 184413.24946481115,\n            \"cpu_time\": 184020.3426124197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4671,\n            \"real_time\": 153759.2164419024,\n            \"cpu_time\": 150529.86512524085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5454,\n            \"real_time\": 122550.22002193381,\n            \"cpu_time\": 117459.66263292996,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5677,\n            \"real_time\": 118082.17368332973,\n            \"cpu_time\": 118350.36110621807,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6404,\n            \"real_time\": 107563.22610855168,\n            \"cpu_time\": 107354.77826358526,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7338,\n            \"real_time\": 94512.12864547076,\n            \"cpu_time\": 95819.70564186428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 194416074.9999355,\n            \"cpu_time\": 195312500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 61618063.63632588,\n            \"cpu_time\": 61079545.45454545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41292594.11766885,\n            \"cpu_time\": 40441176.47058824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 33157647.82608154,\n            \"cpu_time\": 31929347.826086957,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 20907515.151520785,\n            \"cpu_time\": 20833333.333333332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 16060631.818184199,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 14373813.207539398,\n            \"cpu_time\": 14445754.716981132,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 12140977.586207964,\n            \"cpu_time\": 12122844.827586208,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 11818566.101699278,\n            \"cpu_time\": 11917372.881355932,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 12474183.05084173,\n            \"cpu_time\": 12447033.898305085,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 15330244.444440823,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 15240334.782625405,\n            \"cpu_time\": 15285326.086956521,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_taskflow/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 530070.0000007055,\n            \"cpu_time\": 31250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_taskflow/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 655714.800000169,\n            \"cpu_time\": 78125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_taskflow/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 553511.0000000714,\n            \"cpu_time\": 93750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_taskflow/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 683684.3999999473,\n            \"cpu_time\": 78125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_taskflow/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 529424.0000002901,\n            \"cpu_time\": 62500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_taskflow/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 566112.9000000074,\n            \"cpu_time\": 93750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_taskflow/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1008582.3999997956,\n            \"cpu_time\": 171875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_taskflow/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1520637.7000004067,\n            \"cpu_time\": 281250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_taskflow/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 1579156.5999998057,\n            \"cpu_time\": 140625.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_taskflow/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 2060363.6999994705,\n            \"cpu_time\": 187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_taskflow/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 2633048.8999992665,\n            \"cpu_time\": 296875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_taskflow/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 3749334.399999498,\n            \"cpu_time\": 281250.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_taskflow/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 41611268.00000602,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_taskflow/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 30974307.999995288,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_taskflow/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 21487643.99999891,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_taskflow/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 16418552.000004638,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_taskflow/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 11053179.000000454,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_taskflow/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 8297672.999997304,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_taskflow/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 6320484.000007127,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_taskflow/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 140,\n            \"real_time\": 6408918.571423783,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_taskflow/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 188,\n            \"real_time\": 6326315.957450905,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_taskflow/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 233,\n            \"real_time\": 6700124.034334154,\n            \"cpu_time\": 134120.17167381974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_taskflow/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 226,\n            \"real_time\": 6581888.495575748,\n            \"cpu_time\": 69137.16814159292,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_taskflow/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 223,\n            \"real_time\": 6319112.107622977,\n            \"cpu_time\": 70067.26457399104,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_taskflow/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 411014485.7143366,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_taskflow/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 385221509.09085953,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_taskflow/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 228389069.9999574,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_taskflow/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 170449150.0000586,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_taskflow/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 116734610.00000314,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_taskflow/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 87824870.00007677,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_taskflow/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 59986899.999967135,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_taskflow/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 52921700.00002443,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_taskflow/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 70141750.00003889,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_taskflow/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 60708569.99995158,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_taskflow/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 62731880.000046656,\n            \"cpu_time\": 1562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_taskflow/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_taskflow/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10,\n            \"real_time\": 60175500.0000594,\n            \"cpu_time\": 1562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187646,\n            \"real_time\": 3730.466943069201,\n            \"cpu_time\": 3747.0822719375847,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 182616,\n            \"real_time\": 3837.7929644697133,\n            \"cpu_time\": 3850.2924168747536,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 182461,\n            \"real_time\": 3838.174185171489,\n            \"cpu_time\": 3853.5632272101984,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 181544,\n            \"real_time\": 3846.697219407341,\n            \"cpu_time\": 3786.9607367910808,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 651369,\n            \"real_time\": 3776.0300229212608,\n            \"cpu_time\": 3766.106461928646,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180785,\n            \"real_time\": 3268.643969359266,\n            \"cpu_time\": 3197.859335674973,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180282,\n            \"real_time\": 3907.4644168556215,\n            \"cpu_time\": 3900.1397810097515,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 177636,\n            \"real_time\": 3930.4048728813827,\n            \"cpu_time\": 3958.2348172667703,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 637615,\n            \"real_time\": 3989.4425319353586,\n            \"cpu_time\": 3994.377484845871,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 173004,\n            \"real_time\": 3010.6535108992152,\n            \"cpu_time\": 2980.4224179787752,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 446317,\n            \"real_time\": 1198.065724584539,\n            \"cpu_time\": 1190.297479145988,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 314947,\n            \"real_time\": 1980.133482777899,\n            \"cpu_time\": 1984.4608775444758,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 187,\n            \"real_time\": 3740731.016040369,\n            \"cpu_time\": 3760026.7379679144,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 371,\n            \"real_time\": 1883934.2318081206,\n            \"cpu_time\": 1895215.6334231806,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 554,\n            \"real_time\": 1263728.158845147,\n            \"cpu_time\": 1269178.7003610109,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 732,\n            \"real_time\": 958718.169399642,\n            \"cpu_time\": 960553.2786885246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1047,\n            \"real_time\": 641319.8662841313,\n            \"cpu_time\": 641714.4221585483,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1338,\n            \"real_time\": 518581.76382622484,\n            \"cpu_time\": 513826.60687593423,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1857,\n            \"real_time\": 356296.33818012616,\n            \"cpu_time\": 353392.56865912763,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2129,\n            \"real_time\": 337820.90183176304,\n            \"cpu_time\": 337599.81211836543,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5387,\n            \"real_time\": 200108.1678115046,\n            \"cpu_time\": 188532.57842955264,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3079,\n            \"real_time\": 299582.39688189875,\n            \"cpu_time\": 299407.27508931473,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4746,\n            \"real_time\": 115051.05351870028,\n            \"cpu_time\": 115228.61356932153,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7731,\n            \"real_time\": 88691.24304753881,\n            \"cpu_time\": 86906.60975294269,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 374883649.99990153,\n            \"cpu_time\": 375000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 188763274.99992839,\n            \"cpu_time\": 187500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 125939799.99989338,\n            \"cpu_time\": 127604166.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 94210857.14296038,\n            \"cpu_time\": 93750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11,\n            \"real_time\": 62940163.63633339,\n            \"cpu_time\": 63920454.54545455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 47400453.33334517,\n            \"cpu_time\": 46875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22,\n            \"real_time\": 31880404.54547676,\n            \"cpu_time\": 31960227.272727273,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24358575.86207366,\n            \"cpu_time\": 24245689.655172415,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 38,\n            \"real_time\": 17466794.73683942,\n            \"cpu_time\": 17269736.842105262,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 16123037.209306562,\n            \"cpu_time\": 16351744.186046511,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14825679.591829576,\n            \"cpu_time\": 14349489.795918368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14073414.2857155,\n            \"cpu_time\": 13711734.693877552,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3910156,\n            \"real_time\": 192.2742980076355,\n            \"cpu_time\": 187.81219982016063,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3215419,\n            \"real_time\": 205.48336002239023,\n            \"cpu_time\": 204.09470740827246,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3697844,\n            \"real_time\": 196.89473109197567,\n            \"cpu_time\": 190.14458154535453,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2967162,\n            \"real_time\": 197.20288275484938,\n            \"cpu_time\": 194.84106361567046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3681221,\n            \"real_time\": 199.85670515299455,\n            \"cpu_time\": 199.49223369094113,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3547248,\n            \"real_time\": 187.27078005261265,\n            \"cpu_time\": 185.00257100715822,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3507699,\n            \"real_time\": 201.62063506587606,\n            \"cpu_time\": 200.45192019041542,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static_chunk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3306012,\n            \"real_time\": 205.15763403159514,\n            \"cpu_time\": 203.2282399458925,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static_chunk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3462311,\n            \"real_time\": 198.33362745290478,\n            \"cpu_time\": 198.56679541496993,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static_chunk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3404659,\n            \"real_time\": 178.6664097637409,\n            \"cpu_time\": 178.98268225980928,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static_chunk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4751306,\n            \"real_time\": 178.29036900576847,\n            \"cpu_time\": 177.582753036744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/1000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static_chunk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3355036,\n            \"real_time\": 163.33538596906,\n            \"cpu_time\": 163.0012315814197,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2159,\n            \"real_time\": 323817.9712827316,\n            \"cpu_time\": 325671.6072255674,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4113,\n            \"real_time\": 171379.60126434005,\n            \"cpu_time\": 170951.85995623632,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8531,\n            \"real_time\": 92488.05532755857,\n            \"cpu_time\": 93409.33067635681,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8764,\n            \"real_time\": 74053.08078496974,\n            \"cpu_time\": 74880.19169329073,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12693,\n            \"real_time\": 143621.0352162593,\n            \"cpu_time\": 141564.24801071457,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 105607.98000005889,\n            \"cpu_time\": 103125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16028,\n            \"real_time\": 101100.01247812397,\n            \"cpu_time\": 101385.07611679561,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static_chunk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9834,\n            \"real_time\": 70435.1128737466,\n            \"cpu_time\": 71499.38987187309,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static_chunk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12237,\n            \"real_time\": 60386.18125356959,\n            \"cpu_time\": 60012.66650322791,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static_chunk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10462,\n            \"real_time\": 57965.637545421516,\n            \"cpu_time\": 58246.51118333015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static_chunk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12967,\n            \"real_time\": 57691.15446899306,\n            \"cpu_time\": 56634.14822241074,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/1000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static_chunk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11392,\n            \"real_time\": 59418.51299160697,\n            \"cpu_time\": 56234.63834269663,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 78483666.66662008,\n            \"cpu_time\": 78125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41169217.64708583,\n            \"cpu_time\": 41360294.11764706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 28242983.99998952,\n            \"cpu_time\": 28125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 21180703.030316208,\n            \"cpu_time\": 20833333.333333332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 45,\n            \"real_time\": 16190713.333324108,\n            \"cpu_time\": 16319444.444444444,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 12248960.344816718,\n            \"cpu_time\": 12392241.379310345,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 10048331.481475206,\n            \"cpu_time\": 10127314.814814815,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/16/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static_chunk/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 14065754.285716789,\n            \"cpu_time\": 14062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/24/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static_chunk/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 51,\n            \"real_time\": 14432186.274515355,\n            \"cpu_time\": 14093137.25490196,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/32/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static_chunk/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 13959443.999992799,\n            \"cpu_time\": 13750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/48/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static_chunk/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 12739289.999990432,\n            \"cpu_time\": 11875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static_chunk/64/100000000/real_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static_chunk/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 13805658.490573993,\n            \"cpu_time\": 13856132.075471697,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3818945,\n            \"real_time\": 214.8759146832803,\n            \"cpu_time\": 204.572205150899,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3838243,\n            \"real_time\": 184.85424190175684,\n            \"cpu_time\": 183.18928739008967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3848245,\n            \"real_time\": 186.1500242318718,\n            \"cpu_time\": 186.77345127454203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3723668,\n            \"real_time\": 189.46434000006246,\n            \"cpu_time\": 188.8259103658006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3735768,\n            \"real_time\": 183.17901432866043,\n            \"cpu_time\": 184.03177070953015,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3549968,\n            \"real_time\": 183.08029818856406,\n            \"cpu_time\": 184.86082128064254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3673609,\n            \"real_time\": 202.8756462649379,\n            \"cpu_time\": 204.15890749396576,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3212313,\n            \"real_time\": 203.9823952395753,\n            \"cpu_time\": 204.292047505956,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3411334,\n            \"real_time\": 195.44996180388623,\n            \"cpu_time\": 187.79310381217437,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3484350,\n            \"real_time\": 209.1117425058522,\n            \"cpu_time\": 210.76384404551783,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3554234,\n            \"real_time\": 176.10947956722984,\n            \"cpu_time\": 175.8466099868495,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/1000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3693072,\n            \"real_time\": 191.20899890395674,\n            \"cpu_time\": 190.39027671272046,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2155,\n            \"real_time\": 324569.3271462236,\n            \"cpu_time\": 326276.10208816704,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5558,\n            \"real_time\": 136130.04677943318,\n            \"cpu_time\": 132129.3630802447,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4686,\n            \"real_time\": 154167.13615030114,\n            \"cpu_time\": 150048.01536491676,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9778,\n            \"real_time\": 71027.16301899514,\n            \"cpu_time\": 71908.87707097566,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9643,\n            \"real_time\": 112624.12112415681,\n            \"cpu_time\": 111803.89920149332,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10117,\n            \"real_time\": 82501.13670060049,\n            \"cpu_time\": 81854.79885341505,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14106,\n            \"real_time\": 66408.68424784356,\n            \"cpu_time\": 66461.08039132284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10000,\n            \"real_time\": 56800.8700000064,\n            \"cpu_time\": 53125.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6778,\n            \"real_time\": 122143.70020648718,\n            \"cpu_time\": 108346.85748008262,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5587,\n            \"real_time\": 103202.05834970773,\n            \"cpu_time\": 103476.82119205299,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3436,\n            \"real_time\": 196126.65890572494,\n            \"cpu_time\": 190992.43306169964,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/1000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4953,\n            \"real_time\": 160799.7173429243,\n            \"cpu_time\": 154578.0335150414,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_auto_chunk/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 82591800.00004563,\n            \"cpu_time\": 80357142.85714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_auto_chunk/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41079200.00002623,\n            \"cpu_time\": 40441176.47058824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_auto_chunk/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25,\n            \"real_time\": 27999328.000005335,\n            \"cpu_time\": 28125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_auto_chunk/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 32,\n            \"real_time\": 21934681.250002086,\n            \"cpu_time\": 21972656.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_auto_chunk/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 15146919.047613967,\n            \"cpu_time\": 15252976.19047619,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_auto_chunk/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 56,\n            \"real_time\": 14263171.428573126,\n            \"cpu_time\": 14229910.714285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_auto_chunk/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 13808664.285716077,\n            \"cpu_time\": 13839285.714285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/16/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_auto_chunk/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 57,\n            \"real_time\": 12556296.491215777,\n            \"cpu_time\": 12061403.50877193,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/24/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_auto_chunk/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 60,\n            \"real_time\": 12636908.333327787,\n            \"cpu_time\": 12239583.333333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/32/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_auto_chunk/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 54,\n            \"real_time\": 13286983.333340753,\n            \"cpu_time\": 13020833.333333334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/48/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_auto_chunk/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 53,\n            \"real_time\": 13240339.622636795,\n            \"cpu_time\": 13266509.433962265,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_auto_chunk/64/100000000/real_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_auto_chunk/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 52,\n            \"real_time\": 13301409.61538116,\n            \"cpu_time\": 12019230.76923077,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"simple_pool_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:09:52-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"simple_pool_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6625,\n            \"real_time\": 110.34019622635448,\n            \"cpu_time\": 108.49056603773585,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 11201,\n            \"real_time\": 61.096116418232064,\n            \"cpu_time\": 59.98348361753415,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10543,\n            \"real_time\": 65.82905245180723,\n            \"cpu_time\": 66.6911694963483,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10451,\n            \"real_time\": 66.21044876082574,\n            \"cpu_time\": 67.27825088508277,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9390,\n            \"real_time\": 73.65813631521854,\n            \"cpu_time\": 71.55218317358893,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9519,\n            \"real_time\": 74.59586090976644,\n            \"cpu_time\": 73.86542704065553,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7851,\n            \"real_time\": 89.01725894788872,\n            \"cpu_time\": 89.55865494841422,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8502,\n            \"real_time\": 82.66290284639199,\n            \"cpu_time\": 80.86332627617031,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3540,\n            \"real_time\": 199.71918079115676,\n            \"cpu_time\": 198.6228813559322,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2026,\n            \"real_time\": 378.6000987169127,\n            \"cpu_time\": 377.89980256663375,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 932,\n            \"real_time\": 687.1267167380328,\n            \"cpu_time\": 687.3658798283262,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 813,\n            \"real_time\": 873.793603936454,\n            \"cpu_time\": 864.8523985239852,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 542,\n            \"real_time\": 1394.85276752724,\n            \"cpu_time\": 1354.9354243542437,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 787,\n            \"real_time\": 830.3519695039215,\n            \"cpu_time\": 833.8627700127065,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 892,\n            \"real_time\": 788.4571748878452,\n            \"cpu_time\": 753.2230941704036,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 873,\n            \"real_time\": 804.4626575024355,\n            \"cpu_time\": 805.4123711340206,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 794,\n            \"real_time\": 864.0049118391016,\n            \"cpu_time\": 865.8690176322418,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 863,\n            \"real_time\": 806.9064889923275,\n            \"cpu_time\": 796.6396292004634,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 634,\n            \"real_time\": 1084.3216088332003,\n            \"cpu_time\": 1059.7397476340693,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 489,\n            \"real_time\": 1462.9511247454159,\n            \"cpu_time\": 1405.9304703476482,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 282,\n            \"real_time\": 2309.0762411353767,\n            \"cpu_time\": 2327.127659574468,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 194,\n            \"real_time\": 3841.8216494832936,\n            \"cpu_time\": 3865.979381443299,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 78,\n            \"real_time\": 8936.300000000183,\n            \"cpu_time\": 8814.102564102564,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/10000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 61,\n            \"real_time\": 10631.54754099175,\n            \"cpu_time\": 10502.04918032787,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 754986.5999999384,\n            \"cpu_time\": 765625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 187431.95000001835,\n            \"cpu_time\": 187500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 189270.47500005754,\n            \"cpu_time\": 179687.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 198268.33333354443,\n            \"cpu_time\": 197916.66666666666,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 269627.0000001277,\n            \"cpu_time\": 273437.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 194687.624999915,\n            \"cpu_time\": 195312.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 200951.36666683783,\n            \"cpu_time\": 203125.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 211672.6666666485,\n            \"cpu_time\": 213541.66666666666,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 235006.60000020918,\n            \"cpu_time\": 234375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 544083.4000000905,\n            \"cpu_time\": 546875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1025400.8000001705,\n            \"cpu_time\": 1000000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1310981.9999999672,\n            \"cpu_time\": 1312500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28909,\n            \"real_time\": 24.277716282106763,\n            \"cpu_time\": 24.32201044657373,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12475,\n            \"real_time\": 56.13552705407945,\n            \"cpu_time\": 55.11022044088176,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10717,\n            \"real_time\": 195.84133619485556,\n            \"cpu_time\": 196.82513763179995,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 678.2534999993003,\n            \"cpu_time\": 671.875,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1811,\n            \"real_time\": 404.57178354494965,\n            \"cpu_time\": 396.8801766979569,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 893,\n            \"real_time\": 646.0160134384197,\n            \"cpu_time\": 647.3964165733482,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 648,\n            \"real_time\": 915.6794753091253,\n            \"cpu_time\": 916.2808641975308,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 804,\n            \"real_time\": 1070.1370646760308,\n            \"cpu_time\": 1068.8743781094527,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 634,\n            \"real_time\": 1043.2820189267852,\n            \"cpu_time\": 1059.7397476340693,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 589,\n            \"real_time\": 1117.476061121439,\n            \"cpu_time\": 1114.176570458404,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 549,\n            \"real_time\": 1635.1648451739231,\n            \"cpu_time\": 1650.7285974499089,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 545,\n            \"real_time\": 1298.4027522947179,\n            \"cpu_time\": 1290.1376146788991,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2900,\n            \"real_time\": 241.26279310339356,\n            \"cpu_time\": 242.45689655172413,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7167,\n            \"real_time\": 95.73643086366705,\n            \"cpu_time\": 93.74563973768662,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1164,\n            \"real_time\": 1548.2915807556512,\n            \"cpu_time\": 1530.2835051546392,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 111,\n            \"real_time\": 7496.027027029724,\n            \"cpu_time\": 7601.351351351352,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 169,\n            \"real_time\": 3877.95562130241,\n            \"cpu_time\": 3883.1360946745563,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84,\n            \"real_time\": 9096.213095236159,\n            \"cpu_time\": 8928.57142857143,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 73,\n            \"real_time\": 9134.03835617317,\n            \"cpu_time\": 8989.72602739726,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 10599.76578948121,\n            \"cpu_time\": 10485.197368421053,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 47,\n            \"real_time\": 11601.289361699835,\n            \"cpu_time\": 11303.191489361701,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 10774.16290322177,\n            \"cpu_time\": 10836.693548387097,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 59,\n            \"real_time\": 11690.830508487741,\n            \"cpu_time\": 11652.542372881357,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/10000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 48,\n            \"real_time\": 12350.17499999458,\n            \"cpu_time\": 12044.270833333334,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 24174.65517242065,\n            \"cpu_time\": 24245.689655172413,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 53904.19069767949,\n            \"cpu_time\": 53415.6976744186,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 680157.2000003944,\n            \"cpu_time\": 687500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 676183.100000344,\n            \"cpu_time\": 671875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 410173.0500001395,\n            \"cpu_time\": 414062.5,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 874569.3999999275,\n            \"cpu_time\": 875000.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 917388.3000003116,\n            \"cpu_time\": 921875.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1147152.100000312,\n            \"cpu_time\": 1140625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1095964.3999995023,\n            \"cpu_time\": 1062500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1450257.8000001449,\n            \"cpu_time\": 1437500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1323019.2000000898,\n            \"cpu_time\": 1312500.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1619255.3999999291,\n            \"cpu_time\": 1578125.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_bulk/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 196472,\n            \"real_time\": 3.6356116902166824,\n            \"cpu_time\": 3.6582820961765545,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_bulk/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6502,\n            \"real_time\": 102.4837588434942,\n            \"cpu_time\": 103.33358966471855,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_bulk/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1817,\n            \"real_time\": 410.48458998371774,\n            \"cpu_time\": 412.7682993946065,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_bulk/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3289,\n            \"real_time\": 228.35810276696577,\n            \"cpu_time\": 228.0328367284889,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_bulk/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3143,\n            \"real_time\": 198.67492841240426,\n            \"cpu_time\": 198.8545975182946,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_bulk/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3593,\n            \"real_time\": 212.9978291119281,\n            \"cpu_time\": 208.73921514055107,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_bulk/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2456,\n            \"real_time\": 383.7573289902642,\n            \"cpu_time\": 381.71824104234526,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_bulk/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2385,\n            \"real_time\": 239.66880503136946,\n            \"cpu_time\": 242.40041928721175,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_bulk/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1796,\n            \"real_time\": 371.0842427619582,\n            \"cpu_time\": 374.0952115812918,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_bulk/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1525,\n            \"real_time\": 436.0011147540807,\n            \"cpu_time\": 440.57377049180326,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_bulk/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3481,\n            \"real_time\": 345.8839126687858,\n            \"cpu_time\": 345.62625682275205,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_bulk/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2197,\n            \"real_time\": 316.0932635414927,\n            \"cpu_time\": 312.92671825216206,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_bulk/1/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21766,\n            \"real_time\": 32.0947395020109,\n            \"cpu_time\": 31.585959753744373,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_bulk/2/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5245,\n            \"real_time\": 151.15673975203256,\n            \"cpu_time\": 151.930409914204,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_bulk/3/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 388,\n            \"real_time\": 4592.246391753506,\n            \"cpu_time\": 4429.768041237114,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_bulk/4/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 142,\n            \"real_time\": 4338.003521131123,\n            \"cpu_time\": 4401.408450704225,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_bulk/6/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 326,\n            \"real_time\": 3333.4457055227253,\n            \"cpu_time\": 3307.1319018404906,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_bulk/8/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 298,\n            \"real_time\": 1873.2697986560129,\n            \"cpu_time\": 1835.1510067114093,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_bulk/12/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 277,\n            \"real_time\": 3412.0469314068737,\n            \"cpu_time\": 3440.884476534296,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_bulk/16/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 209,\n            \"real_time\": 3433.8157894739784,\n            \"cpu_time\": 3438.995215311005,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_bulk/24/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 180,\n            \"real_time\": 4021.7894444443423,\n            \"cpu_time\": 3993.0555555555557,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_bulk/32/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 190,\n            \"real_time\": 3760.596315786595,\n            \"cpu_time\": 3782.8947368421054,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_bulk/48/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 211,\n            \"real_time\": 2546.2014218000245,\n            \"cpu_time\": 2443.7203791469196,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_bulk/64/10000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 261,\n            \"real_time\": 2850.483141764403,\n            \"cpu_time\": 2873.5632183908046,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_bulk/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 220,\n            \"real_time\": 3181.654090907283,\n            \"cpu_time\": 3196.0227272727275,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_bulk/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 19991.609090924834,\n            \"cpu_time\": 19886.363636363636,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_bulk/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5,\n            \"real_time\": 132134.42000014766,\n            \"cpu_time\": 131250.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_bulk/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 380272.5499999724,\n            \"cpu_time\": 378906.25,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_bulk/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 356584.6000001329,\n            \"cpu_time\": 359375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_bulk/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4,\n            \"real_time\": 326526.02500002104,\n            \"cpu_time\": 324218.75,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_bulk/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 390302.8999998241,\n            \"cpu_time\": 390625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/16/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_bulk/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 366209.95000021136,\n            \"cpu_time\": 359375.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/24/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_bulk/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 387441.5999998746,\n            \"cpu_time\": 390625.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/32/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_bulk/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 352939.9499998363,\n            \"cpu_time\": 343750.0,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/48/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_bulk/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 305708.70000004413,\n            \"cpu_time\": 307291.6666666667,\n            \"time_unit\": \"us\"\n          },\n          {\n            \"name\": \"BM_dispenso_bulk/64/1000000/real_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_bulk/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 173304.50000008568,\n            \"cpu_time\": 171875.0,\n            \"time_unit\": \"us\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"small_buffer_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:11:46-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"small_buffer_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 649918.5267858008,\n            \"cpu_time\": 645228.7946428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 249,\n            \"real_time\": 2327006.8273106236,\n            \"cpu_time\": 2321787.1485943776,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5600,\n            \"real_time\": 122091.17857147638,\n            \"cpu_time\": 122767.85714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1445,\n            \"real_time\": 489625.53633217537,\n            \"cpu_time\": 486591.6955017301,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1000,\n            \"real_time\": 513826.20000003953,\n            \"cpu_time\": 500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 4531621.249998352,\n            \"cpu_time\": 4492187.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6400,\n            \"real_time\": 109757.37500004357,\n            \"cpu_time\": 109863.28125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1600,\n            \"real_time\": 438479.1875003202,\n            \"cpu_time\": 439453.125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 915519.308036445,\n            \"cpu_time\": 924246.6517857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 237,\n            \"real_time\": 3777730.379743663,\n            \"cpu_time\": 3757911.3924050634,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4978,\n            \"real_time\": 139625.03013253893,\n            \"cpu_time\": 141246.48453194054,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 558594.1071428481,\n            \"cpu_time\": 544084.8214285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1200,\n            \"real_time\": 60861.78125007298,\n            \"cpu_time\": 1002604.1666666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 160,\n            \"real_time\": 225898.00781389614,\n            \"cpu_time\": 3125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 4480,\n            \"real_time\": 14027.127511199009,\n            \"cpu_time\": 198800.2232142857,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 688,\n            \"real_time\": 51777.78888078719,\n            \"cpu_time\": 953851.7441860465,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 928,\n            \"real_time\": 67333.4455817907,\n            \"cpu_time\": 1077586.2068965517,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 160,\n            \"real_time\": 285637.53906283295,\n            \"cpu_time\": 4492187.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 3776,\n            \"real_time\": 15188.683461341448,\n            \"cpu_time\": 231726.69491525425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1120,\n            \"real_time\": 60007.86272320877,\n            \"cpu_time\": 864955.3571428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1600,\n            \"real_time\": 75147.95312506096,\n            \"cpu_time\": 1093750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 144,\n            \"real_time\": 394780.77256897377,\n            \"cpu_time\": 6184895.833333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1600,\n            \"real_time\": 14773.132812493373,\n            \"cpu_time\": 312500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 480,\n            \"real_time\": 64837.47395845304,\n            \"cpu_time\": 1204427.0833333333,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"small_buffer_shared_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:12:01-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"small_buffer_shared_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 896,\n            \"real_time\": 748380.3571426099,\n            \"cpu_time\": 749860.4910714285,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 264,\n            \"real_time\": 2322325.000002159,\n            \"cpu_time\": 2308238.6363636362,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4978,\n            \"real_time\": 136748.11169155658,\n            \"cpu_time\": 138107.67376456407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 546668.4821434293,\n            \"cpu_time\": 544084.8214285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 513510.35714251985,\n            \"cpu_time\": 488281.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 154,\n            \"real_time\": 4597018.831167612,\n            \"cpu_time\": 4565746.7532467535,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5600,\n            \"real_time\": 122679.41071432429,\n            \"cpu_time\": 122767.85714285714,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 491120.7142859959,\n            \"cpu_time\": 488281.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 640,\n            \"real_time\": 1254287.3437496382,\n            \"cpu_time\": 1269531.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 212,\n            \"real_time\": 3153438.207545888,\n            \"cpu_time\": 3169221.6981132077,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4480,\n            \"real_time\": 149054.9776785802,\n            \"cpu_time\": 146484.375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1120,\n            \"real_time\": 595084.1071426437,\n            \"cpu_time\": 585937.5,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 640,\n            \"real_time\": 60153.906249738044,\n            \"cpu_time\": 805664.0625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 272,\n            \"real_time\": 221986.53492717526,\n            \"cpu_time\": 3791360.294117647,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 4480,\n            \"real_time\": 14595.566406251846,\n            \"cpu_time\": 251116.07142857142,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kSmallSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 768,\n            \"real_time\": 55517.51302087145,\n            \"cpu_time\": 996907.5520833334,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 496,\n            \"real_time\": 61919.997480021404,\n            \"cpu_time\": 1008064.5161290322,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 96,\n            \"real_time\": 296599.54427193233,\n            \"cpu_time\": 5208333.333333333,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 3776,\n            \"real_time\": 14346.227820424781,\n            \"cpu_time\": 223450.74152542374,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kMediumSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1280,\n            \"real_time\": 62205.6005859406,\n            \"cpu_time\": 866699.21875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_newdelete<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 480,\n            \"real_time\": 74954.21875004146,\n            \"cpu_time\": 1041666.6666666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_newdelete<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 112,\n            \"real_time\": 380519.4754450879,\n            \"cpu_time\": 5859375.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/8192/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 1600,\n            \"real_time\": 15871.16015620893,\n            \"cpu_time\": 322265.625,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_small_buffer_allocator<kLargeSize>/32768/threads:16\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 16,\n            \"iterations\": 480,\n            \"real_time\": 72366.75781250311,\n            \"cpu_time\": 1269531.25,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"summing_for_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:12:15-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"summing_for_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4072727,\n            \"real_time\": 165.63020305552206,\n            \"cpu_time\": 161.13282329014442,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3733,\n            \"real_time\": 191584.62362719976,\n            \"cpu_time\": 192539.51245646933,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 40467617.64707566,\n            \"cpu_time\": 40441176.47058824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7379,\n            \"real_time\": 95965.93034283393,\n            \"cpu_time\": 95287.30180241226,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10993,\n            \"real_time\": 62567.788592751866,\n            \"cpu_time\": 62539.79805330665,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10867,\n            \"real_time\": 66087.83472895667,\n            \"cpu_time\": 66140.60918376737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13229,\n            \"real_time\": 55719.6008768989,\n            \"cpu_time\": 55512.51039383173,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13018,\n            \"real_time\": 53579.3209402647,\n            \"cpu_time\": 54011.75295744354,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12685,\n            \"real_time\": 53853.236105647215,\n            \"cpu_time\": 52966.101694915254,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15106,\n            \"real_time\": 47966.7218324109,\n            \"cpu_time\": 48614.7888256322,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16043,\n            \"real_time\": 43952.141120723856,\n            \"cpu_time\": 43827.526023811006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16853,\n            \"real_time\": 42071.109001370045,\n            \"cpu_time\": 41721.05856524061,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16934,\n            \"real_time\": 41295.14586041345,\n            \"cpu_time\": 41521.49521672375,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15802,\n            \"real_time\": 44369.940513872105,\n            \"cpu_time\": 44495.949879762054,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21506,\n            \"real_time\": 33112.1733469637,\n            \"cpu_time\": 32694.364363433462,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1167,\n            \"real_time\": 608633.9331620311,\n            \"cpu_time\": 602506.4267352185,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2859,\n            \"real_time\": 248218.53795055265,\n            \"cpu_time\": 245933.89296956977,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3239,\n            \"real_time\": 197207.87280019786,\n            \"cpu_time\": 197784.81012658228,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2964,\n            \"real_time\": 174024.358974295,\n            \"cpu_time\": 173962.55060728744,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 4979,\n            \"real_time\": 135652.9222735869,\n            \"cpu_time\": 134941.75537256477,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5699,\n            \"real_time\": 124713.75679935279,\n            \"cpu_time\": 126118.61730128093,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6584,\n            \"real_time\": 99408.56622125838,\n            \"cpu_time\": 99673.45078979344,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7328,\n            \"real_time\": 92679.01200873358,\n            \"cpu_time\": 93818.23144104803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8834,\n            \"real_time\": 77913.14240441729,\n            \"cpu_time\": 76055.58071088974,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9753,\n            \"real_time\": 70674.81800470152,\n            \"cpu_time\": 70491.13093407157,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 10421,\n            \"real_time\": 69779.40696671692,\n            \"cpu_time\": 68971.30793589867,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12259,\n            \"real_time\": 57817.8154824973,\n            \"cpu_time\": 58630.39399624766,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 50261871.42857452,\n            \"cpu_time\": 50223214.28571428,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 21100748.48485855,\n            \"cpu_time\": 21306818.181818184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 49,\n            \"real_time\": 14535400.000011355,\n            \"cpu_time\": 14349489.795918368,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 10938712.499992676,\n            \"cpu_time\": 10498046.875,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 70,\n            \"real_time\": 7612709.999999165,\n            \"cpu_time\": 7589285.714285715,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 120,\n            \"real_time\": 5862020.833334706,\n            \"cpu_time\": 5859375.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5012698.999998975,\n            \"cpu_time\": 5000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 4375098.837213997,\n            \"cpu_time\": 4269622.0930232555,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 157,\n            \"real_time\": 4064921.019110611,\n            \"cpu_time\": 4080414.0127388537,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 172,\n            \"real_time\": 4039693.0232556006,\n            \"cpu_time\": 4087936.0465116277,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 170,\n            \"real_time\": 4083682.9411786958,\n            \"cpu_time\": 4136029.411764706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 171,\n            \"real_time\": 4098470.175438983,\n            \"cpu_time\": 3746345.0292397663,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2013996,\n            \"real_time\": 283.97484404163015,\n            \"cpu_time\": 271.53728209986514,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2438738,\n            \"real_time\": 287.415294303854,\n            \"cpu_time\": 281.90810164929565,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2424301,\n            \"real_time\": 288.7592753538838,\n            \"cpu_time\": 290.0320546004807,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2392217,\n            \"real_time\": 291.2505429065487,\n            \"cpu_time\": 287.3903161795105,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2399459,\n            \"real_time\": 292.6986874961101,\n            \"cpu_time\": 286.52292037496784,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2298641,\n            \"real_time\": 297.2038260866358,\n            \"cpu_time\": 292.29227182496095,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2331874,\n            \"real_time\": 291.68175467479045,\n            \"cpu_time\": 294.8272505289737,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2287150,\n            \"real_time\": 297.40874013502855,\n            \"cpu_time\": 300.59244037339045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2312689,\n            \"real_time\": 308.25913038902155,\n            \"cpu_time\": 304.02920582923167,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2017800,\n            \"real_time\": 324.9908315987843,\n            \"cpu_time\": 325.2304490038656,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2118822,\n            \"real_time\": 356.9433864665559,\n            \"cpu_time\": 353.9702721606629,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2056370,\n            \"real_time\": 419.15277892633566,\n            \"cpu_time\": 417.9087421038043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3640,\n            \"real_time\": 186574.36813195448,\n            \"cpu_time\": 184581.04395604396,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1778,\n            \"real_time\": 391835.8830147151,\n            \"cpu_time\": 395458.3802024747,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2613,\n            \"real_time\": 267170.3406047968,\n            \"cpu_time\": 269087.2560275545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3495,\n            \"real_time\": 203913.19027185196,\n            \"cpu_time\": 205650.92989985694,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 5038,\n            \"real_time\": 137883.74354900772,\n            \"cpu_time\": 139564.3112346169,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6362,\n            \"real_time\": 107803.5523420331,\n            \"cpu_time\": 108063.50204338258,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8020,\n            \"real_time\": 92882.73067330717,\n            \"cpu_time\": 93516.20947630923,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7763,\n            \"real_time\": 117187.36313277017,\n            \"cpu_time\": 114726.9096998583,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 26452,\n            \"real_time\": 29895.387872354004,\n            \"cpu_time\": 29534.62876153032,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15704,\n            \"real_time\": 43855.310748823875,\n            \"cpu_time\": 43778.65511971472,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13450,\n            \"real_time\": 56892.74349440751,\n            \"cpu_time\": 56923.79182156134,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 13780,\n            \"real_time\": 45718.8461538357,\n            \"cpu_time\": 45355.587808418,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41011788.23528993,\n            \"cpu_time\": 40441176.47058824,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16,\n            \"real_time\": 44761018.74996629,\n            \"cpu_time\": 44921875.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 29970426.086947557,\n            \"cpu_time\": 29891304.347826086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 33,\n            \"real_time\": 21354400.00000182,\n            \"cpu_time\": 21306818.181818184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 44,\n            \"real_time\": 16108543.181809926,\n            \"cpu_time\": 15980113.636363637,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 64,\n            \"real_time\": 10993362.50000249,\n            \"cpu_time\": 10986328.125,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85,\n            \"real_time\": 7566056.470579283,\n            \"cpu_time\": 7536764.705882353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 115,\n            \"real_time\": 6707372.1739095915,\n            \"cpu_time\": 6657608.695652174,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5014663.000001746,\n            \"cpu_time\": 5000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 168,\n            \"real_time\": 4178838.690477061,\n            \"cpu_time\": 4185267.8571428573,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 171,\n            \"real_time\": 4101583.040938903,\n            \"cpu_time\": 4111842.1052631577,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 171,\n            \"real_time\": 4104495.321637294,\n            \"cpu_time\": 3746345.0292397663,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2493701,\n            \"real_time\": 280.6435093864744,\n            \"cpu_time\": 281.96042749311164,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2463790,\n            \"real_time\": 284.9030964492015,\n            \"cpu_time\": 285.38349453484267,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2449804,\n            \"real_time\": 287.78959459620575,\n            \"cpu_time\": 287.01275693892245,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2375635,\n            \"real_time\": 291.01048772221753,\n            \"cpu_time\": 289.3963087763903,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2423796,\n            \"real_time\": 291.72471610654327,\n            \"cpu_time\": 283.64598340784454,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2395357,\n            \"real_time\": 291.15530586881096,\n            \"cpu_time\": 293.5366210548156,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2434237,\n            \"real_time\": 295.94854568417975,\n            \"cpu_time\": 282.42936082230284,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2302359,\n            \"real_time\": 295.56216037566224,\n            \"cpu_time\": 291.8202591342184,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/24/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2331757,\n            \"real_time\": 318.0313814861727,\n            \"cpu_time\": 314.9449106403455,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/32/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2222777,\n            \"real_time\": 335.5259209537515,\n            \"cpu_time\": 337.41576415447884,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/48/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1743188,\n            \"real_time\": 335.76097357238046,\n            \"cpu_time\": 322.68464445601967,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/64/1000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2020516,\n            \"real_time\": 358.31045138953414,\n            \"cpu_time\": 363.45913618105476,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3620,\n            \"real_time\": 190287.23756883608,\n            \"cpu_time\": 189917.1270718232,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7193,\n            \"real_time\": 97866.87056869271,\n            \"cpu_time\": 97751.28597247324,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9594,\n            \"real_time\": 70381.05065669553,\n            \"cpu_time\": 71659.37043985825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 12696,\n            \"real_time\": 56207.774102109506,\n            \"cpu_time\": 55381.61625708885,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17881,\n            \"real_time\": 41380.25837477722,\n            \"cpu_time\": 40196.297746211065,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20533,\n            \"real_time\": 34965.104952999834,\n            \"cpu_time\": 34243.656552866116,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 25833,\n            \"real_time\": 28104.05682653716,\n            \"cpu_time\": 27822.939650834203,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29324,\n            \"real_time\": 25396.207884334948,\n            \"cpu_time\": 25576.319738098486,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28569,\n            \"real_time\": 25628.362910858246,\n            \"cpu_time\": 25705.309951345866,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14482,\n            \"real_time\": 39538.0541361425,\n            \"cpu_time\": 38841.320259632645,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14674,\n            \"real_time\": 45744.5345508898,\n            \"cpu_time\": 44721.957203216574,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 16921,\n            \"real_time\": 46184.386265578796,\n            \"cpu_time\": 45247.03031735713,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17,\n            \"real_time\": 41278441.17647328,\n            \"cpu_time\": 41360294.11764706,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 30218669.56521041,\n            \"cpu_time\": 29891304.347826086,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 34,\n            \"real_time\": 20743876.470586497,\n            \"cpu_time\": 20680147.05882353,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 43,\n            \"real_time\": 15652655.813958751,\n            \"cpu_time\": 15625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92,\n            \"real_time\": 7662764.13043235,\n            \"cpu_time\": 7642663.043478261,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 76,\n            \"real_time\": 8163021.052627971,\n            \"cpu_time\": 8223684.2105263155,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 6047028.5714293085,\n            \"cpu_time\": 5837912.087912088,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 120,\n            \"real_time\": 4726758.333337481,\n            \"cpu_time\": 4557291.666666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123,\n            \"real_time\": 4290023.577241078,\n            \"cpu_time\": 4319105.691056911,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 4422926.249998227,\n            \"cpu_time\": 4394531.25,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 100,\n            \"real_time\": 5035360.0000016745,\n            \"cpu_time\": 4843750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 160,\n            \"real_time\": 4380931.250000231,\n            \"cpu_time\": 4003906.25,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"timed_task_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:14:11-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"timed_task_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_dispenso<2,false>/manual_time\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00011410507199445439,\n            \"stddev\": 0.00025959161117679964\n          },\n          {\n            \"name\": \"BM_dispenso<4,false>/manual_time\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 9.499403194593473e-05,\n            \"stddev\": 0.00022148459148240075\n          },\n          {\n            \"name\": \"BM_dispenso<6,false>/manual_time\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00011122424800323612,\n            \"stddev\": 0.0002584484966445175\n          },\n          {\n            \"name\": \"BM_dispenso<2,true>/manual_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00021067590805366529,\n            \"stddev\": 0.00032774180372595736\n          },\n          {\n            \"name\": \"BM_dispenso<4,true>/manual_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.00012264779616308292,\n            \"stddev\": 0.00024850180966736076\n          },\n          {\n            \"name\": \"BM_dispenso<6,true>/manual_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0001564002840850341,\n            \"stddev\": 0.00028391568381329395\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"family_index\": 6,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 5.8251430668715325e-05,\n            \"stddev\": 0.00018424238583588737\n          },\n          {\n            \"name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"family_index\": 7,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0001699293040307555,\n            \"stddev\": 0.0002952365190105025\n          },\n          {\n            \"name\": \"BM_folly<2,false>/manual_time\",\n            \"family_index\": 8,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005680985280046283,\n            \"stddev\": 0.0005642962547763239\n          },\n          {\n            \"name\": \"BM_folly<4,false>/manual_time\",\n            \"family_index\": 9,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005455392239974363,\n            \"stddev\": 0.0005558913424860759\n          },\n          {\n            \"name\": \"BM_folly<6,false>/manual_time\",\n            \"family_index\": 10,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0005332746680010663,\n            \"stddev\": 0.0006059270038487692\n          },\n          {\n            \"name\": \"BM_folly<2,true>/manual_time\",\n            \"family_index\": 11,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<2,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0009192386400182341,\n            \"stddev\": 0.0005620669852732883\n          },\n          {\n            \"name\": \"BM_folly<4,true>/manual_time\",\n            \"family_index\": 12,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<4,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0008921381915636856,\n            \"stddev\": 0.0004929507789989129\n          },\n          {\n            \"name\": \"BM_folly<6,true>/manual_time\",\n            \"family_index\": 13,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly<6,true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0008487736196124131,\n            \"stddev\": 0.00045440981516014855\n          },\n          {\n            \"name\": \"BM_folly_mixed<false>/manual_time\",\n            \"family_index\": 14,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<false>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007231684653297855,\n            \"stddev\": 0.0005998303041159766\n          },\n          {\n            \"name\": \"BM_folly_mixed<true>/manual_time\",\n            \"family_index\": 15,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_folly_mixed<true>/manual_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 7,\n            \"real_time\": 100000000.0,\n            \"cpu_time\": 0.0,\n            \"time_unit\": \"ns\",\n            \"mean\": 0.0007927332290995415,\n            \"stddev\": 0.0005397679052957852\n          }\n        ]\n      }\n    },\n    {\n      \"name\": \"trivial_compute_benchmark\",\n      \"success\": true,\n      \"data\": {\n        \"context\": {\n          \"date\": \"2026-03-20T09:14:40-07:00\",\n          \"host_name\": \"windows-bench\",\n          \"executable\": \"trivial_compute_benchmark.exe\",\n          \"num_cpus\": 64,\n          \"mhz_per_cpu\": 2500,\n          \"caches\": [\n            {\n              \"type\": \"Data\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Instruction\",\n              \"level\": 1,\n              \"size\": 32768,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 2,\n              \"size\": 1048576,\n              \"num_sharing\": 2\n            },\n            {\n              \"type\": \"Unified\",\n              \"level\": 3,\n              \"size\": 34603008,\n              \"num_sharing\": 32\n            }\n          ],\n          \"load_avg\": [],\n          \"library_build_type\": \"release\"\n        },\n        \"benchmarks\": [\n          {\n            \"name\": \"BM_serial<kSmallSize>\",\n            \"family_index\": 0,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kSmallSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 89600,\n            \"real_time\": 8072.840401790619,\n            \"cpu_time\": 8196.14955357143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kMediumSize>\",\n            \"family_index\": 1,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kMediumSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 9,\n            \"real_time\": 90999777.77784969,\n            \"cpu_time\": 92013888.8888889,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_serial<kLargeSize>\",\n            \"family_index\": 2,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_serial<kLargeSize>\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7970337799.99947,\n            \"cpu_time\": 7953125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_tbb/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17905,\n            \"real_time\": 39884.28930467646,\n            \"cpu_time\": 39269.75705110304,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_tbb/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22140,\n            \"real_time\": 31430.38843723694,\n            \"cpu_time\": 31758.130081300813,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_tbb/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19605,\n            \"real_time\": 31214.695230832833,\n            \"cpu_time\": 30285.64141800561,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_tbb/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22820,\n            \"real_time\": 32296.577563510007,\n            \"cpu_time\": 32181.20070113935,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_tbb/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22591,\n            \"real_time\": 31171.23190649365,\n            \"cpu_time\": 31124.12022486831,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_tbb/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22843,\n            \"real_time\": 30344.09665979791,\n            \"cpu_time\": 30096.747362430502,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_tbb/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22780,\n            \"real_time\": 29450.223880596433,\n            \"cpu_time\": 29494.073748902545,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_tbb/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 22251,\n            \"real_time\": 31696.94395757417,\n            \"cpu_time\": 30897.4877533594,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_tbb/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 19821,\n            \"real_time\": 32137.197921382132,\n            \"cpu_time\": 32320.51864184451,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_tbb/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 20543,\n            \"real_time\": 33922.67439030511,\n            \"cpu_time\": 33466.38757727693,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_tbb/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 17795,\n            \"real_time\": 39177.04973306321,\n            \"cpu_time\": 39512.50351222253,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_tbb/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28791,\n            \"real_time\": 23799.781181623777,\n            \"cpu_time\": 23878.989962140946,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_tbb/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 6,\n            \"real_time\": 114842633.33325846,\n            \"cpu_time\": 111979166.66666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_tbb/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 45232699.999966525,\n            \"cpu_time\": 44791666.666666664,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_tbb/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 30166578.260832466,\n            \"cpu_time\": 29211956.52173913,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_tbb/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 31,\n            \"real_time\": 22630087.096771486,\n            \"cpu_time\": 22681451.612903226,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_tbb/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 15176271.739145033,\n            \"cpu_time\": 15285326.086956521,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_tbb/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 62,\n            \"real_time\": 11396609.677420553,\n            \"cpu_time\": 11340725.806451613,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_tbb/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 92,\n            \"real_time\": 7612427.17391289,\n            \"cpu_time\": 7472826.0869565215,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_tbb/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 122,\n            \"real_time\": 5816072.1311472375,\n            \"cpu_time\": 5763319.672131147,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_tbb/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 144,\n            \"real_time\": 4536531.944444909,\n            \"cpu_time\": 4557291.666666667,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_tbb/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 183,\n            \"real_time\": 3924480.8743161066,\n            \"cpu_time\": 3927595.6284153005,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_tbb/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 252,\n            \"real_time\": 2749477.777775783,\n            \"cpu_time\": 2728174.603174603,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/1000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_tbb/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 275,\n            \"real_time\": 2581395.6363642565,\n            \"cpu_time\": 2556818.1818181816,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/1/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_tbb/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 11798446499.999954,\n            \"cpu_time\": 11671875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/2/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_tbb/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3921351299.9995146,\n            \"cpu_time\": 3875000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/3/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_tbb/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2611634500.0000367,\n            \"cpu_time\": 2578125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/4/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_tbb/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1959720800.0004685,\n            \"cpu_time\": 1953125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/6/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_tbb/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1307265999.9997995,\n            \"cpu_time\": 1296875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/8/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_tbb/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 983014100.0002186,\n            \"cpu_time\": 984375000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/12/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_tbb/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 658705300.0002925,\n            \"cpu_time\": 640625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/16/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_tbb/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 510544100.00051576,\n            \"cpu_time\": 500000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/24/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_tbb/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 524089900.0000354,\n            \"cpu_time\": 515625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/32/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_tbb/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 527799899.9999909,\n            \"cpu_time\": 515625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/48/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_tbb/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 279121349.9999685,\n            \"cpu_time\": 281250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_tbb/64/100000000/real_time\",\n            \"family_index\": 3,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_tbb/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 3,\n            \"real_time\": 277920633.33314824,\n            \"cpu_time\": 265625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85416,\n            \"real_time\": 8194.632153224366,\n            \"cpu_time\": 8231.771565046362,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85378,\n            \"real_time\": 8200.924125655556,\n            \"cpu_time\": 8235.435358054769,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85382,\n            \"real_time\": 8208.993698898777,\n            \"cpu_time\": 8235.049542058045,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85084,\n            \"real_time\": 8210.547223910802,\n            \"cpu_time\": 8263.892153636407,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85250,\n            \"real_time\": 8211.580058653659,\n            \"cpu_time\": 8064.5161290322585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85240,\n            \"real_time\": 8211.550915062888,\n            \"cpu_time\": 8065.462224307837,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84894,\n            \"real_time\": 8225.209084263233,\n            \"cpu_time\": 7914.281339081678,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84553,\n            \"real_time\": 8275.614111854047,\n            \"cpu_time\": 8130.994760682649,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84214,\n            \"real_time\": 8283.037262208562,\n            \"cpu_time\": 8349.264967820078,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84688,\n            \"real_time\": 8325.585679190948,\n            \"cpu_time\": 8302.534007179293,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 82658,\n            \"real_time\": 8419.918217231101,\n            \"cpu_time\": 8506.436158629534,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 80961,\n            \"real_time\": 8715.408653548191,\n            \"cpu_time\": 8491.742937957782,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 90152174.99995743,\n            \"cpu_time\": 87890625.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 15,\n            \"real_time\": 45173566.66668396,\n            \"cpu_time\": 45833333.333333336,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 23,\n            \"real_time\": 30222656.521761127,\n            \"cpu_time\": 30570652.173913043,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 29,\n            \"real_time\": 22694403.448283616,\n            \"cpu_time\": 22629310.344827585,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 46,\n            \"real_time\": 15322123.913036825,\n            \"cpu_time\": 15285326.086956521,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 58,\n            \"real_time\": 11436237.93103839,\n            \"cpu_time\": 11584051.72413793,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 91,\n            \"real_time\": 7971884.615381986,\n            \"cpu_time\": 7898351.648351648,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 116,\n            \"real_time\": 5826082.7586231055,\n            \"cpu_time\": 5792025.862068965,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 177,\n            \"real_time\": 4384141.807909891,\n            \"cpu_time\": 4325564.971751412,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 198,\n            \"real_time\": 3530944.4444437483,\n            \"cpu_time\": 3551136.3636363638,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 228,\n            \"real_time\": 3137914.9122825,\n            \"cpu_time\": 3015350.8771929825,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/1000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 227,\n            \"real_time\": 3131572.687223701,\n            \"cpu_time\": 3028634.3612334803,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/1/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7959612399.9999695,\n            \"cpu_time\": 7953125000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/2/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 4335119400.000622,\n            \"cpu_time\": 4343750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/3/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2660708999.9997697,\n            \"cpu_time\": 2640625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/4/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2002838999.999767,\n            \"cpu_time\": 2000000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/6/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1336128599.9999382,\n            \"cpu_time\": 1312500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/8/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1004162499.9994383,\n            \"cpu_time\": 1000000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/12/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 673378100.0002637,\n            \"cpu_time\": 671875000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/16/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 528924399.99959606,\n            \"cpu_time\": 531250000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/24/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 354444800.0002376,\n            \"cpu_time\": 351562500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/32/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 265958699.99982825,\n            \"cpu_time\": 257812500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/48/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 284690399.9998176,\n            \"cpu_time\": 289062500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso/64/100000000/real_time\",\n            \"family_index\": 4,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 283763350.0002994,\n            \"cpu_time\": 273437500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 0,\n            \"run_name\": \"BM_dispenso_static/1/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85770,\n            \"real_time\": 8170.67739303006,\n            \"cpu_time\": 8197.796432318994,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 1,\n            \"run_name\": \"BM_dispenso_static/2/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85664,\n            \"real_time\": 8172.214699286489,\n            \"cpu_time\": 8207.94032499066,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 2,\n            \"run_name\": \"BM_dispenso_static/3/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85592,\n            \"real_time\": 8176.984998595961,\n            \"cpu_time\": 8032.292737639032,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 3,\n            \"run_name\": \"BM_dispenso_static/4/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85334,\n            \"real_time\": 8177.017367055757,\n            \"cpu_time\": 8239.681721236553,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 4,\n            \"run_name\": \"BM_dispenso_static/6/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85484,\n            \"real_time\": 8189.980581161395,\n            \"cpu_time\": 8225.223433625006,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 5,\n            \"run_name\": \"BM_dispenso_static/8/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85561,\n            \"real_time\": 8194.99187713534,\n            \"cpu_time\": 8217.821203585745,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 6,\n            \"run_name\": \"BM_dispenso_static/12/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85251,\n            \"real_time\": 8194.353145422458,\n            \"cpu_time\": 8247.703839251153,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 7,\n            \"run_name\": \"BM_dispenso_static/16/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 85040,\n            \"real_time\": 8220.970131707054,\n            \"cpu_time\": 8268.167920978363,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 8,\n            \"run_name\": \"BM_dispenso_static/24/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84686,\n            \"real_time\": 8234.149682353822,\n            \"cpu_time\": 7933.719859244739,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 9,\n            \"run_name\": \"BM_dispenso_static/32/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 84139,\n            \"real_time\": 8262.935143037008,\n            \"cpu_time\": 8171.002745456923,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 10,\n            \"run_name\": \"BM_dispenso_static/48/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 83857,\n            \"real_time\": 8549.29701754648,\n            \"cpu_time\": 8571.138962758028,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 11,\n            \"run_name\": \"BM_dispenso_static/64/100/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 81512,\n            \"real_time\": 8642.213416427257,\n            \"cpu_time\": 8626.03052311316,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 12,\n            \"run_name\": \"BM_dispenso_static/1/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 8,\n            \"real_time\": 89947212.49996473,\n            \"cpu_time\": 89843750.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 13,\n            \"run_name\": \"BM_dispenso_static/2/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 14,\n            \"real_time\": 50276828.57137603,\n            \"cpu_time\": 51339285.71428572,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 14,\n            \"run_name\": \"BM_dispenso_static/3/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 21,\n            \"real_time\": 33563195.23811094,\n            \"cpu_time\": 33482142.85714286,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 15,\n            \"run_name\": \"BM_dispenso_static/4/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 28,\n            \"real_time\": 25172449.99999743,\n            \"cpu_time\": 24553571.42857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 16,\n            \"run_name\": \"BM_dispenso_static/6/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 42,\n            \"real_time\": 16789247.619033717,\n            \"cpu_time\": 16741071.42857143,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 17,\n            \"run_name\": \"BM_dispenso_static/8/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 50,\n            \"real_time\": 12676171.99999222,\n            \"cpu_time\": 12500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 18,\n            \"run_name\": \"BM_dispenso_static/12/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 75,\n            \"real_time\": 8789814.666658156,\n            \"cpu_time\": 8541666.666666666,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 19,\n            \"run_name\": \"BM_dispenso_static/16/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 99,\n            \"real_time\": 7168474.747470669,\n            \"cpu_time\": 7260101.01010101,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 20,\n            \"run_name\": \"BM_dispenso_static/24/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 123,\n            \"real_time\": 6172592.682922526,\n            \"cpu_time\": 5970528.455284553,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 21,\n            \"run_name\": \"BM_dispenso_static/32/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 146,\n            \"real_time\": 4363375.3424641425,\n            \"cpu_time\": 4387842.465753425,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 22,\n            \"run_name\": \"BM_dispenso_static/48/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 176,\n            \"real_time\": 4016964.204543621,\n            \"cpu_time\": 3995028.409090909,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 23,\n            \"run_name\": \"BM_dispenso_static/64/1000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 184,\n            \"real_time\": 3782068.478259411,\n            \"cpu_time\": 3736413.0434782607,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 24,\n            \"run_name\": \"BM_dispenso_static/1/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 7927653300.000202,\n            \"cpu_time\": 7875000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 25,\n            \"run_name\": \"BM_dispenso_static/2/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 3955117200.0001316,\n            \"cpu_time\": 3937500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 26,\n            \"run_name\": \"BM_dispenso_static/3/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 2642757199.9993234,\n            \"cpu_time\": 2640625000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 27,\n            \"run_name\": \"BM_dispenso_static/4/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1982501099.9993536,\n            \"cpu_time\": 1968750000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 28,\n            \"run_name\": \"BM_dispenso_static/6/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 1326344799.999788,\n            \"cpu_time\": 1312500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 29,\n            \"run_name\": \"BM_dispenso_static/8/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 997577999.9995211,\n            \"cpu_time\": 1000000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 30,\n            \"run_name\": \"BM_dispenso_static/12/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 675283999.9999197,\n            \"cpu_time\": 687500000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 31,\n            \"run_name\": \"BM_dispenso_static/16/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 518762899.99927396,\n            \"cpu_time\": 500000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 32,\n            \"run_name\": \"BM_dispenso_static/24/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 1,\n            \"real_time\": 503509899.999699,\n            \"cpu_time\": 500000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 33,\n            \"run_name\": \"BM_dispenso_static/32/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 382804600.0003269,\n            \"cpu_time\": 375000000.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 34,\n            \"run_name\": \"BM_dispenso_static/48/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 365750599.9999557,\n            \"cpu_time\": 367187500.0,\n            \"time_unit\": \"ns\"\n          },\n          {\n            \"name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"family_index\": 5,\n            \"per_family_instance_index\": 35,\n            \"run_name\": \"BM_dispenso_static/64/100000000/real_time\",\n            \"run_type\": \"iteration\",\n            \"repetitions\": 1,\n            \"repetition_index\": 0,\n            \"threads\": 1,\n            \"iterations\": 2,\n            \"real_time\": 296345549.99984175,\n            \"cpu_time\": 289062500.0,\n            \"time_unit\": \"ns\"\n          }\n        ]\n      }\n    }\n  ]\n}"
  },
  {
    "path": "run_bench.bat",
    "content": "REM Copyright (c) Meta Platforms, Inc. and affiliates.\nREM\nREM This source code is licensed under the MIT license found in the\nREM LICENSE file in the root directory of this source tree.\n\n@echo off\nREM Windows launcher for dispenso benchmarks\nREM Sets up Visual Studio build environment and runs run_benchmarks.py\nREM Output: benchmark_results.json with system info and benchmark results\ncall \"C:\\Program Files (x86)\\Microsoft Visual Studio\\18\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64 -host_arch=amd64\nset PATH=%PATH%;C:\\vcpkg\\installed\\x64-windows\\bin\npython -u scripts\\run_benchmarks.py --build --high-priority --min-time 1.5 -o benchmark_results.json --cmake-args=\"-G\" --cmake-args=\"Visual Studio 18 2026\" --cmake-args=\"-A\" --cmake-args=\"x64\" --cmake-args=\"-DCMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows\" --cmake-args=\"-DCMAKE_DISABLE_FIND_PACKAGE_OpenMP=ON\" %*\n"
  },
  {
    "path": "scripts/BENCHMARKING.md",
    "content": "# Benchmark Generation Guide\n\nThis guide covers building dispenso benchmarks and generating performance\ncharts for the 1.5.0 release across Linux, Mac, and Windows.\n\n## Prerequisites\n\n```bash\npip install matplotlib pandas\n```\n\n## Quick Start (Build + Run)\n\nThe simplest way to build and run benchmarks is with `run_benchmarks.py --build`:\n\n```bash\n# Build and run all benchmarks\npython3 scripts/run_benchmarks.py --build \\\n  -o results/my-platform.json\n\n# Build and run only pipeline benchmark\npython3 scripts/run_benchmarks.py --build -B pipeline \\\n  -o results/my-platform.json\n\n# Use a custom compiler\npython3 scripts/run_benchmarks.py --build \\\n  --cmake-args=\"-DCMAKE_CXX_COMPILER=g++-13\" \\\n  -o results/my-platform.json\n\n# Clean rebuild with custom build directory\npython3 scripts/run_benchmarks.py --build --clean \\\n  -b /tmp/dispenso-bench \\\n  -o results/my-platform.json\n```\n\nThe script auto-detects your platform (e.g., `linux-threadripper-96c`,\n`macos-m4-12c`) and includes it in the output. Override with `--platform`:\n\n```bash\npython3 scripts/run_benchmarks.py --build \\\n  --platform my-custom-label \\\n  -o results/my-custom-label.json\n```\n\n### Build Flags\n\n| Flag | Description |\n|------|-------------|\n| `--build` | Enable cmake configure + build before running |\n| `--build-dir` / `-b` | Build directory (default: `/tmp/dispenso-build`) |\n| `--source-dir` / `-s` | Dispenso source root (default: auto-detected) |\n| `--jobs` / `-j` | Parallel build jobs (default: all cores) |\n| `--clean` | Wipe build directory before configuring |\n| `--cmake-args` | Extra cmake flags (repeatable) |\n\n## Per-Platform Manual Build\n\nIf you prefer to configure and build manually, or need to pass\nplatform-specific options not covered by `--cmake-args`:\n\n### Linux\n\n```bash\nmkdir /tmp/dispenso-bench && cd /tmp/dispenso-bench\ncmake <path-to-dispenso> \\\n  -DDISPENSO_BUILD_TESTS=OFF \\\n  -DDISPENSO_BUILD_BENCHMARKS=ON \\\n  -DCMAKE_BUILD_TYPE=Release \\\n  -DCMAKE_CXX_STANDARD=20 \\\n  -DCMAKE_CXX_COMPILER=/opt/rh/gcc-toolset-13/root/usr/bin/g++ \\\n  -DFETCHCONTENT_SOURCE_DIR_TASKFLOW=~/dispenso_deps/taskflow-3.11.0\ncmake --build . -j$(nproc)\n```\n\n### Mac\n\n```bash\nmkdir /tmp/dispenso-bench && cd /tmp/dispenso-bench\ncmake <path-to-dispenso> \\\n  -DDISPENSO_BUILD_TESTS=OFF \\\n  -DDISPENSO_BUILD_BENCHMARKS=ON \\\n  -DCMAKE_BUILD_TYPE=Release \\\n  -DCMAKE_CXX_STANDARD=20 \\\n  -DFETCHCONTENT_SOURCE_DIR_TASKFLOW=~/dispenso_deps/taskflow-3.11.0\ncmake --build . -j$(sysctl -n hw.ncpu)\n```\n\nIf using Homebrew GCC instead of Xcode clang, add:\n```\n  -DCMAKE_CXX_COMPILER=g++-13\n```\n\n### Windows\n\n```bat\nmkdir C:\\tmp\\dispenso-bench && cd C:\\tmp\\dispenso-bench\ncmake <path-to-dispenso> ^\n  -DDISPENSO_BUILD_TESTS=OFF ^\n  -DDISPENSO_BUILD_BENCHMARKS=ON ^\n  -DCMAKE_BUILD_TYPE=Release ^\n  -DCMAKE_CXX_STANDARD=20 ^\n  -DFETCHCONTENT_SOURCE_DIR_TASKFLOW=C:\\dispenso_deps\\taskflow-3.11.0\ncmake --build . --config Release -j\n```\n\nThen run benchmarks against the existing build:\n\n```bash\npython3 scripts/run_benchmarks.py \\\n  -b /tmp/dispenso-bench \\\n  -o results/<platform-name>.json\n```\n\n## Step 1: Run Benchmarks\n\nAfter building (either via `--build` or manually), run all benchmarks and\ncapture results as JSON:\n\n```bash\npython3 scripts/run_benchmarks.py \\\n  -b /tmp/dispenso-bench \\\n  -o results/<platform-name>.json\n```\n\nWhere `<platform-name>` is a descriptive identifier like `linux-threadripper-96c`,\n`macos-m4-12c`, `windows-zen4-24c`, etc. (auto-detected if omitted).\n\n### Run Options\n\n- `-B <regex>` — filter which benchmark executables to run\n  (e.g. `-B \"pipeline|simple_pool\"`)\n- `-f <pattern>` — filter individual test cases within benchmarks\n  (passed to `--benchmark_filter`)\n- `--min-time <seconds>` — minimum time per benchmark\n- `--tcmalloc <path>` — use tcmalloc via LD_PRELOAD\n- `-p <name>` — override auto-detected platform identifier\n\n## Step 2: Generate Charts\n\nGenerate per-platform charts from the JSON results:\n\n```bash\npython3 scripts/generate_charts.py \\\n  -i results/<platform-name>.json \\\n  -o docs/benchmarks/ \\\n  --platform <platform-name>\n```\n\nCharts are written to `docs/benchmarks/<platform-name>/`.\n\n## Step 3: Compose Multi-Platform Landing Page\n\nAfter collecting JSON from all platforms, generate a unified landing page:\n\n```bash\npython3 scripts/update_benchmarks.py --compose \\\n  linux-threadripper:results/linux.json \\\n  macos-m2:results/macos.json \\\n  windows-zen4:results/windows.json\n```\n\nThis creates per-platform subdirectories under `docs/benchmarks/` and a\nunified `benchmark_results.md` landing page.\n\n## All-in-One (Single Platform)\n\n`update_benchmarks.py` can build, run, chart, and update docs in one command:\n\n```bash\npython3 scripts/update_benchmarks.py \\\n  --platform linux-threadripper\n\n# Or with an existing build:\npython3 scripts/update_benchmarks.py \\\n  -b /tmp/dispenso-bench \\\n  --skip-build \\\n  --platform linux-threadripper\n```\n\n## Notes\n\n- Build directories should be in `/tmp` (or equivalent) to avoid polluting\n  the source tree\n- Taskflow must be available locally (FetchContent fallback requires internet)\n- The benchmark runner automatically collects machine info (CPU, cores, memory)\n  and includes it in the JSON output\n- Platform identifiers are auto-detected from machine info when not specified\n- Chart names are mapped to README-expected filenames via `README_CHART_MAPPING`\n  in `update_benchmarks.py`\n"
  },
  {
    "path": "scripts/compare_benchmarks.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"\nCompare dispenso benchmark results across multiple runs.\n\nShows side-by-side timing and percentage change for each benchmark test.\nUseful for A/B testing optimization changes.\n\nUsage:\n    python scripts/compare_benchmarks.py baseline.json after.json\n    python scripts/compare_benchmarks.py baseline.json v2.json v3.json --filter concurrent_vector\n    python scripts/compare_benchmarks.py baseline.json after.json --prefix BM_dispenso\n\"\"\"\n\nimport argparse\nimport json\nimport sys\nfrom pathlib import Path\nfrom typing import Dict, List, Optional\n\n\ndef format_time(ns: float) -> str:\n    \"\"\"Format nanoseconds into a human-readable string.\"\"\"\n    if ns < 1000:\n        return f\"{ns:.0f}ns\"\n    elif ns < 1e6:\n        return f\"{ns / 1e3:.1f}us\"\n    elif ns < 1e9:\n        return f\"{ns / 1e6:.1f}ms\"\n    else:\n        return f\"{ns / 1e9:.2f}s\"\n\n\ndef _pct_change(val: float, base_val: float) -> Optional[float]:\n    \"\"\"Return percentage change from base_val to val, or None if base is zero.\"\"\"\n    if base_val == 0:\n        return None\n    return ((val - base_val) / base_val) * 100\n\n\n_TIME_UNIT_MULTIPLIERS = {\"us\": 1000, \"ms\": 1e6, \"s\": 1e9}\n\n\ndef _normalize_to_ns(time_val: float, unit: str) -> float:\n    \"\"\"Convert a time value to nanoseconds based on its unit string.\"\"\"\n    return time_val * _TIME_UNIT_MULTIPLIERS.get(unit, 1)\n\n\ndef load_benchmarks(\n    path: Path,\n    file_filter: Optional[str] = None,\n) -> Dict[str, float]:\n    \"\"\"Load benchmark results, returning {test_name: time_ns}.\n\n    When --benchmark_repetitions is used, Google Benchmark outputs both\n    individual iteration rows (run_type=iteration) and aggregate rows\n    (run_type=aggregate) with names like \"BM_foo_median\", \"BM_foo_mean\", etc.\n    We prefer the median aggregate when available, falling back to the\n    individual iteration row.\n    \"\"\"\n    with open(path) as f:\n        data = json.load(f)\n\n    iteration_results = {}\n    median_results = {}\n    for entry in data.get(\"results\", []):\n        if not entry.get(\"success\"):\n            continue\n        exe_name = entry[\"name\"].replace(\".exe\", \"\")\n        if file_filter and file_filter.lower() not in exe_name.lower():\n            continue\n        for bm in entry.get(\"data\", {}).get(\"benchmarks\", []):\n            name = bm[\"name\"]\n            time_ns = _normalize_to_ns(bm[\"real_time\"], bm.get(\"time_unit\", \"ns\"))\n\n            run_type = bm.get(\"run_type\")\n            if run_type == \"iteration\":\n                if name not in iteration_results:\n                    iteration_results[name] = time_ns\n            elif run_type == \"aggregate\" and name.endswith(\"_median\"):\n                base_name = name[: -len(\"_median\")]\n                median_results[base_name] = time_ns\n\n    # Prefer median aggregates over raw iteration values\n    results = {}\n    for name in set(list(iteration_results.keys()) + list(median_results.keys())):\n        if name in median_results:\n            results[name] = median_results[name]\n        elif name in iteration_results:\n            results[name] = iteration_results[name]\n    return results\n\n\ndef get_compiler_info(path: Path) -> str:\n    \"\"\"Extract compiler summary from benchmark file.\"\"\"\n    with open(path) as f:\n        data = json.load(f)\n    mi = data.get(\"machine_info\", {})\n    compiler = mi.get(\"compiler\", {})\n    return compiler.get(\"compiler_summary\", \"unknown\")\n\n\ndef _format_comparison_cell(val: Optional[float], base_val: Optional[float]) -> str:\n    \"\"\"Format one comparison column cell (time + percentage change).\"\"\"\n    if val is None:\n        return f\"  {'---':>10} {'':>7}\"\n    cell = f\"  {format_time(val):>10}\"\n    if base_val is None:\n        return cell + f\" {'N/A':>7}\"\n    pct = _pct_change(val, base_val)\n    if pct is None:\n        return cell + f\" {'N/A':>7}\"\n    marker = \" <<<\" if abs(pct) > 15 else \"\"\n    return cell + f\" {pct:>+6.1f}%{marker}\"\n\n\ndef _print_summary(\n    datasets: List[Dict[str, float]],\n    labels: List[str],\n    tests: List[str],\n):\n    \"\"\"Print summary of significant changes (>10%) vs baseline.\"\"\"\n    base_label = labels[0]\n    for i, label in enumerate(labels[1:], 1):\n        improvements = []\n        regressions = []\n        for test in tests:\n            base_val = datasets[0].get(test)\n            val = datasets[i].get(test)\n            if base_val is None or val is None:\n                continue\n            pct = _pct_change(val, base_val)\n            if pct is None:\n                continue\n            if pct < -10:\n                improvements.append((test, pct))\n            elif pct > 10:\n                regressions.append((test, pct))\n\n        print(f\"[{label}] vs [{base_label}] significant changes (>10%):\")\n        if improvements:\n            for test, pct in sorted(improvements, key=lambda x: x[1]):\n                print(f\"  {pct:>+7.1f}%  {test}\")\n        if regressions:\n            for test, pct in sorted(regressions, key=lambda x: -x[1]):\n                print(f\"  {pct:>+7.1f}%  {test}\")\n        if not improvements and not regressions:\n            print(\"  (none)\")\n        print()\n\n\ndef compare(\n    files: List[Path],\n    labels: List[str],\n    file_filter: Optional[str] = None,\n    prefix_filter: Optional[str] = None,\n):\n    \"\"\"Compare benchmark results across files.\"\"\"\n    datasets = [load_benchmarks(path, file_filter) for path in files]\n\n    # Print headers with compiler info\n    print(\"Runs:\")\n    for i, (path, label) in enumerate(zip(files, labels)):\n        compiler = get_compiler_info(path)\n        count = len(datasets[i])\n        print(f\"  [{label}] {path.name} ({compiler}, {count} tests)\")\n    print()\n\n    # Collect and filter test names\n    all_tests = set()\n    for ds in datasets:\n        all_tests.update(ds.keys())\n    if prefix_filter:\n        all_tests = {t for t in all_tests if t.startswith(prefix_filter)}\n\n    if not all_tests:\n        print(\"No matching tests found.\")\n        return\n\n    tests = sorted(all_tests)\n    name_width = min(max(len(t) for t in tests), 55)\n\n    # Print header\n    base_label = labels[0]\n    header = f\"{'Test':<{name_width}}  {base_label:>10}\"\n    for label in labels[1:]:\n        header += f\"  {label:>10} {'chg%':>7}\"\n    print(header)\n    print(\"-\" * len(header))\n\n    # Print each test row\n    for test in tests:\n        name = test if len(test) <= name_width else test[: name_width - 2] + \"..\"\n        base_val = datasets[0].get(test)\n\n        line = f\"{name:<{name_width}}\"\n        line += (\n            f\"  {format_time(base_val):>10}\"\n            if base_val is not None\n            else f\"  {'---':>10}\"\n        )\n        for i in range(1, len(labels)):\n            line += _format_comparison_cell(datasets[i].get(test), base_val)\n        print(line)\n\n    print()\n    _print_summary(datasets, labels, tests)\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Compare dispenso benchmark results across runs\"\n    )\n    parser.add_argument(\n        \"files\",\n        type=Path,\n        nargs=\"+\",\n        help=\"Benchmark JSON files (first is baseline, rest are compared against it)\",\n    )\n    parser.add_argument(\n        \"--labels\",\n        type=str,\n        default=None,\n        help=\"Comma-separated labels for each file (default: base,v2,v3,...)\",\n    )\n    parser.add_argument(\n        \"--filter\",\n        type=str,\n        default=None,\n        help=\"Filter to benchmark files matching this substring (e.g., 'concurrent_vector')\",\n    )\n    parser.add_argument(\n        \"--prefix\",\n        type=str,\n        default=None,\n        help=\"Filter to test names starting with this prefix (e.g., 'BM_dispenso')\",\n    )\n\n    args = parser.parse_args()\n\n    for f in args.files:\n        if not f.exists():\n            print(f\"Error: {f} not found\")\n            sys.exit(1)\n\n    if args.labels:\n        labels = args.labels.split(\",\")\n        if len(labels) != len(args.files):\n            print(f\"Error: {len(labels)} labels for {len(args.files)} files\")\n            sys.exit(1)\n    else:\n        labels = [\"base\"] + [f\"v{i + 1}\" for i in range(len(args.files) - 1)]\n\n    compare(args.files, labels, args.filter, args.prefix)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/generate_charts.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"\nChart generator for dispenso benchmarks.\n\nThis script takes benchmark results (JSON from run_benchmarks.py) and generates\ncomparison charts and a markdown report.\n\nUsage:\n    python generate_charts.py --input results.json --output-dir charts/\n\nRequirements:\n    pip install matplotlib pandas\n\"\"\"\n\nimport argparse\nimport json\nimport re\nfrom pathlib import Path\nfrom typing import Any, Dict, List\n\ntry:\n    import matplotlib.pyplot as plt\n    import pandas as pd\n\n    HAS_PLOTTING = True\nexcept ImportError:\n    HAS_PLOTTING = False\n    print(\"Error: matplotlib/pandas required for chart generation\")\n    print(\"Install with: pip install matplotlib pandas\")\n\n\n# Consistent color palette for libraries across all charts\nLIBRARY_COLORS = {\n    # Primary libraries\n    \"dispenso\": \"#2ecc71\",  # Green\n    \"tbb\": \"#3498db\",  # Blue\n    \"omp\": \"#e74c3c\",  # Red\n    \"folly\": \"#9b59b6\",  # Purple\n    \"taskflow\": \"#f39c12\",  # Orange\n    # Standard library variants\n    \"std\": \"#1abc9c\",  # Teal\n    \"vector\": \"#1abc9c\",  # Teal (same as std)\n    \"deque\": \"#e67e22\",  # Dark orange\n    \"serial\": \"#95a5a6\",  # Gray\n    # Dispenso variants\n    \"dispenso2\": \"#27ae60\",  # Darker green\n    \"dispenso auto chunk\": \"#58d68d\",  # Lighter green\n    \"dispenso static chunk\": \"#1e8449\",  # Dark green\n    \"dispenso mostly idle\": \"#82e0aa\",  # Pale green\n    \"dispenso very idle\": \"#abebc6\",  # Very pale green\n    # TBB variants\n    \"tbb concurrent vector\": \"#5dade2\",  # Light blue\n    # Async\n    \"async\": \"#f1c40f\",  # Yellow\n}\n\n\ndef get_library_color(name: str) -> str:\n    \"\"\"Get consistent color for a library name.\"\"\"\n    name_lower = name.lower().replace(\"_\", \" \")\n\n    # Try exact match first\n    if name_lower in LIBRARY_COLORS:\n        return LIBRARY_COLORS[name_lower]\n\n    # Try prefix matching\n    for key, color in LIBRARY_COLORS.items():\n        if name_lower.startswith(key) or key in name_lower:\n            return color\n\n    # Default color for unknown libraries\n    return \"#7f8c8d\"  # Gray\n\n\ndef get_time_scale(values, original_unit: str = \"ns\"):\n    \"\"\"Determine appropriate time unit and scale factor for display.\n\n    Returns (scale_factor, display_unit) where:\n    - scale_factor: divide values by this to get display values\n    - display_unit: string label for the axis (e.g., \"ms\", \"µs\")\n\n    This avoids matplotlib's scientific notation by choosing appropriate units.\n    \"\"\"\n    max_val = max(values) if len(values) > 0 else 0\n\n    if original_unit == \"ns\":\n        if max_val >= 1e9:\n            return 1e9, \"s\"\n        elif max_val >= 1e6:\n            return 1e6, \"ms\"\n        elif max_val >= 1e3:\n            return 1e3, \"µs\"\n        else:\n            return 1, \"ns\"\n    elif original_unit == \"us\":\n        if max_val >= 1e6:\n            return 1e6, \"s\"\n        elif max_val >= 1e3:\n            return 1e3, \"ms\"\n        else:\n            return 1, \"µs\"\n    elif original_unit == \"ms\":\n        if max_val >= 1e3:\n            return 1e3, \"s\"\n        else:\n            return 1, \"ms\"\n    else:\n        return 1, original_unit\n\n\ndef extract_benchmark_data(results: List[Dict]) -> \"pd.DataFrame\":\n    \"\"\"Extract benchmark data into a DataFrame for plotting.\"\"\"\n    rows = []\n\n    for result in results:\n        if not result.get(\"success\") or \"data\" not in result:\n            continue\n\n        data = result[\"data\"]\n        benchmarks = data.get(\"benchmarks\", [])\n\n        for bm in benchmarks:\n            row = {\n                \"suite\": result[\"name\"].replace(\"_benchmark\", \"\"),\n                \"name\": bm.get(\"name\", \"unknown\"),\n                \"real_time\": bm.get(\"real_time\", 0),\n                \"cpu_time\": bm.get(\"cpu_time\", 0),\n                \"time_unit\": bm.get(\"time_unit\", \"ns\"),\n                \"iterations\": bm.get(\"iterations\", 0),\n                \"skipped\": bm.get(\"error_occurred\", False),\n                \"error_message\": bm.get(\"error_message\", \"\"),\n            }\n\n            # Extract any custom counters\n            for key, value in bm.items():\n                if key not in row and isinstance(value, (int, float)):\n                    row[key] = value\n\n            rows.append(row)\n\n    return pd.DataFrame(rows)\n\n\ndef parse_benchmark_name(name: str) -> Dict[str, Any]:\n    \"\"\"Parse benchmark name to extract library, threads, worksize from patterns like:\n    BM_library/threads/worksize/real_time or BM_library<template>\n    \"\"\"\n    result = {\"library\": name, \"threads\": None, \"worksize\": None, \"raw\": name}\n\n    # Handle template-style names like BM_serial<kSmallSize>\n    if \"<\" in name and \">\" in name:\n        match = re.match(r\"([^<]+)<([^>]+)>\", name)\n        if match:\n            result[\"library\"] = match.group(1)\n            result[\"worksize\"] = match.group(2)\n        return result\n\n    # Handle slash-delimited names like BM_dispenso/8/1000/real_time\n    parts = name.split(\"/\")\n    # Filter out \"real_time\" suffix if present\n    if parts and parts[-1] == \"real_time\":\n        parts = parts[:-1]\n\n    if len(parts) >= 3:\n        # Pattern: library/threads/worksize\n        result[\"library\"] = parts[0]\n        try:\n            result[\"threads\"] = int(parts[1])\n            result[\"worksize\"] = parts[2]\n        except (ValueError, IndexError):\n            pass\n    elif len(parts) == 2:\n        # Pattern: library/threads (no worksize, e.g., BM_dispenso_very_idle/8)\n        result[\"library\"] = parts[0]\n        try:\n            result[\"threads\"] = int(parts[1])\n            result[\"worksize\"] = \"default\"\n        except ValueError:\n            pass\n\n    return result\n\n\ndef generate_line_chart(\n    suite: str,\n    suite_df: \"pd.DataFrame\",\n    output_dir: Path,\n    worksize: str,\n) -> Path:\n    \"\"\"Generate a line chart for thread scaling benchmarks.\"\"\"\n    fig, ax = plt.subplots(figsize=(12, 8))\n\n    # Get data for this worksize\n    ws_df = suite_df[suite_df[\"worksize\"] == worksize].copy()\n    if ws_df.empty:\n        plt.close()\n        return None\n\n    # Determine appropriate time units\n    original_unit = ws_df[\"time_unit\"].iloc[0]\n    scale, display_unit = get_time_scale(ws_df[\"real_time\"].values, original_unit)\n\n    # Group by library and plot each as a line\n    libraries = sorted(ws_df[\"library\"].unique())\n\n    has_data = False\n    for lib in libraries:\n        lib_df = ws_df[ws_df[\"library\"] == lib].sort_values(\"threads\")\n        # Filter out invalid results (time = 0 or near 0, often indicates failed runs)\n        lib_df = lib_df[lib_df[\"real_time\"] > 0.01]\n        if not lib_df.empty and lib_df[\"threads\"].notna().any():\n            # Clean up library name for legend\n            label = lib.replace(\"BM_\", \"\").replace(\"_\", \" \")\n            color = get_library_color(label)\n            ax.plot(\n                lib_df[\"threads\"],\n                lib_df[\"real_time\"] / scale,\n                marker=\"o\",\n                label=label,\n                color=color,\n                linewidth=2,\n                markersize=6,\n            )\n            has_data = True\n\n    if not has_data:\n        plt.close()\n        return None\n\n    # Format worksize for title\n    ws_display = worksize\n    if worksize.isdigit():\n        ws_int = int(worksize)\n        if ws_int >= 1000000:\n            ws_display = f\"{ws_int // 1000000}M\"\n        elif ws_int >= 1000:\n            ws_display = f\"{ws_int // 1000}K\"\n\n    # Clean up suite name for title\n    suite_display = suite.replace(\"_\", \" \").title()\n\n    ax.set_xlabel(\"Threads\", fontsize=12)\n    ax.set_ylabel(f\"Time ({display_unit})\", fontsize=12)\n    ax.set_title(f\"{suite_display} - {ws_display} Elements\", fontsize=14)\n    ax.grid(True, alpha=0.3)\n    ax.tick_params(axis=\"both\", labelsize=10)\n    ax.legend(\n        loc=\"upper center\",\n        bbox_to_anchor=(0.5, -0.08),\n        ncol=min(5, len(libraries)),\n        fontsize=11,\n    )\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{suite}_{worksize}_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    return chart_path\n\n\ndef generate_bar_chart(suite: str, suite_df: \"pd.DataFrame\", output_dir: Path) -> Path:\n    \"\"\"Generate a vertical bar chart for simple benchmarks.\"\"\"\n    import numpy as np\n\n    # For simple benchmarks, just show each benchmark as its own bar\n    # Skip the complex operation/library parsing that causes issues\n\n    num_bars = len(suite_df)\n    fig_width = max(10, min(20, num_bars * 1.2))\n    fig, ax = plt.subplots(figsize=(fig_width, 8))\n\n    # Sort for logical grouping: serial implementations first, then parallel\n    # Within each group: serial baseline first, then dispenso, then others alphabetically\n    def library_order(lib):\n        lib_lower = lib.lower()\n        if lib_lower == \"serial\":\n            return (0, lib_lower)  # Serial baseline first\n        elif lib_lower.startswith(\"dispenso\"):\n            return (1, lib_lower)  # Dispenso second\n        elif lib_lower.startswith(\"taskflow\"):\n            return (2, lib_lower)  # Taskflow third\n        else:\n            return (3, lib_lower)  # Others (tbb, etc.) alphabetically after\n\n    def sort_key(name):\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        # Group parallel implementations after serial ones\n        is_parallel = \"_par\" in clean or clean.endswith(\"par\")\n        # Extract library name for ordering\n        lib = clean.replace(\"_par\", \"\").replace(\" par\", \"\")\n        return (1 if is_parallel else 0, library_order(lib))\n\n    suite_df_sorted = suite_df.copy()\n    suite_df_sorted[\"sort_key\"] = suite_df_sorted[\"name\"].apply(sort_key)\n    suite_df_sorted = suite_df_sorted.sort_values(\"sort_key\")\n    suite_df_sorted = suite_df_sorted.drop(columns=[\"sort_key\"])\n\n    # Clean up labels and get colors\n    labels = suite_df_sorted[\"name\"].apply(\n        lambda x: x.replace(\"BM_\", \"\").replace(\"/real_time\", \"\").replace(\"_\", \" \")\n    )\n    colors = [get_library_color(label) for label in labels]\n\n    # Convert to sensible units based on max value\n    max_val = suite_df_sorted[\"real_time\"].max()\n    original_unit = suite_df_sorted[\"time_unit\"].iloc[0]\n\n    # Determine best display unit and scale factor\n    if original_unit == \"ns\":\n        if max_val >= 1e9:\n            scale = 1e9\n            display_unit = \"s\"\n        elif max_val >= 1e6:\n            scale = 1e6\n            display_unit = \"ms\"\n        elif max_val >= 1e3:\n            scale = 1e3\n            display_unit = \"µs\"\n        else:\n            scale = 1\n            display_unit = \"ns\"\n    else:\n        scale = 1\n        display_unit = original_unit\n\n    scaled_values = suite_df_sorted[\"real_time\"] / scale\n\n    x = np.arange(len(labels))\n    bars = ax.bar(x, scaled_values, color=colors)\n\n    ax.set_xticks(x)\n    ax.set_xticklabels(labels, rotation=45, ha=\"right\", fontsize=10)\n\n    # Clean up suite name for title\n    suite_display = suite.replace(\"_\", \" \").title()\n\n    ax.set_ylabel(f\"Time ({display_unit})\", fontsize=12)\n    ax.set_title(f\"{suite_display} Benchmark Results\", fontsize=14)\n    ax.grid(axis=\"y\", alpha=0.3)\n    ax.tick_params(axis=\"y\", labelsize=10)\n\n    # Add value labels on top of bars\n    max_scaled = scaled_values.max()\n    for bar, val in zip(bars, scaled_values):\n        # Format value for display\n        if val >= 1000:\n            label = f\"{val:.0f}\"\n        elif val >= 100:\n            label = f\"{val:.1f}\"\n        elif val >= 10:\n            label = f\"{val:.1f}\"\n        else:\n            label = f\"{val:.2f}\"\n\n        ax.text(\n            bar.get_x() + bar.get_width() / 2,\n            bar.get_height(),\n            label,\n            ha=\"center\",\n            va=\"bottom\",\n            fontsize=9,\n            rotation=90 if num_bars > 15 else 0,\n        )\n\n    # Add some headroom for labels\n    ax.set_ylim(0, max_scaled * 1.15)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{suite}_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    return chart_path\n\n\ndef generate_grouped_bar_chart(\n    suite: str,\n    suite_df: \"pd.DataFrame\",\n    output_dir: Path,\n    operations: list,\n    libraries: list,\n) -> Path:\n    \"\"\"Generate a grouped vertical bar chart comparing libraries per operation.\"\"\"\n    import numpy as np\n\n    num_ops = len(operations)\n    num_libs = len(libraries)\n    fig_width = max(12, min(24, num_ops * num_libs * 0.4))\n    fig, ax = plt.subplots(figsize=(fig_width, 8))\n\n    x = np.arange(num_ops)\n    width = 0.8 / num_libs\n\n    max_val = 0\n    for i, lib in enumerate(libraries):\n        lib_df = suite_df[suite_df[\"lib\"] == lib]\n        values = []\n        for op in operations:\n            op_df = lib_df[lib_df[\"operation\"] == op]\n            if not op_df.empty:\n                values.append(op_df[\"real_time\"].iloc[0])\n            else:\n                values.append(0)\n\n        values = np.array(values)\n        max_val = max(max_val, values.max())\n        color = get_library_color(lib)\n        bars = ax.bar(\n            x + i * width - width * num_libs / 2 + width / 2,\n            values,\n            width,\n            label=lib,\n            color=color,\n        )\n\n        # Add value labels\n        for bar, val in zip(bars, values):\n            if val > 0:\n                if val >= 1e9:\n                    label = f\"{val / 1e9:.1f}B\"\n                elif val >= 1e6:\n                    label = f\"{val / 1e6:.1f}M\"\n                elif val >= 1e3:\n                    label = f\"{val / 1e3:.1f}K\"\n                else:\n                    label = f\"{val:.0f}\"\n\n                ax.text(\n                    bar.get_x() + bar.get_width() / 2,\n                    bar.get_height(),\n                    label,\n                    ha=\"center\",\n                    va=\"bottom\",\n                    fontsize=8,\n                    rotation=90,\n                )\n\n    ax.set_xticks(x)\n    ax.set_xticklabels(operations, rotation=45, ha=\"right\", fontsize=10)\n\n    suite_display = suite.replace(\"_\", \" \").title()\n    ax.set_ylabel(f\"Time ({suite_df['time_unit'].iloc[0]})\", fontsize=12)\n    ax.set_title(f\"{suite_display} Benchmark Results\", fontsize=14)\n    ax.legend(loc=\"upper right\", fontsize=11)\n    ax.grid(axis=\"y\", alpha=0.3)\n    ax.tick_params(axis=\"y\", labelsize=10)\n    ax.set_ylim(0, max_val * 1.2)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{suite}_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    return chart_path\n\n\ndef generate_horizontal_grouped_bar_chart(\n    title: str,\n    suite_df: \"pd.DataFrame\",\n    output_dir: Path,\n    chart_name: str,\n) -> Path:\n    \"\"\"Generate a horizontal grouped bar chart with log scale for comparing libraries.\"\"\"\n    import numpy as np\n\n    # Parse benchmark names to extract operation and library\n    def parse_cv_benchmark(name: str):\n        \"\"\"Parse concurrent_vector benchmark name into operation and library.\"\"\"\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        # Library prefixes\n        lib_prefixes = [\"std_\", \"deque_\", \"tbb_\", \"dispenso_\"]\n        for prefix in lib_prefixes:\n            if clean.startswith(prefix):\n                lib = prefix.rstrip(\"_\")\n                op = clean[len(prefix) :]\n                # Map library names to display names\n                lib_map = {\n                    \"std\": \"std::vector\",\n                    \"deque\": \"std::deque\",\n                    \"tbb\": \"tbb::concurrent_vector\",\n                    \"dispenso\": \"dispenso::ConcurrentVector\",\n                }\n                return op, lib_map.get(lib, lib)\n        return clean, \"unknown\"\n\n    suite_df = suite_df.copy()\n    parsed = suite_df[\"name\"].apply(parse_cv_benchmark)\n    suite_df[\"operation\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"lib\"] = parsed.apply(lambda x: x[1])\n\n    # Get unique operations and libraries\n    operations = suite_df[\"operation\"].unique().tolist()\n    libraries = [\n        \"std::vector\",\n        \"std::deque\",\n        \"tbb::concurrent_vector\",\n        \"dispenso::ConcurrentVector\",\n    ]\n    libraries = [lib for lib in libraries if lib in suite_df[\"lib\"].values]\n\n    num_ops = len(operations)\n    num_libs = len(libraries)\n    fig_height = max(6, num_ops * 0.5)\n    fig, ax = plt.subplots(figsize=(12, fig_height))\n\n    y = np.arange(num_ops)\n    height = 0.8 / num_libs\n\n    # Library colors\n    lib_colors = {\n        \"std::vector\": \"#808080\",  # gray\n        \"std::deque\": \"#FF8C00\",  # orange\n        \"tbb::concurrent_vector\": \"#4285F4\",  # blue\n        \"dispenso::ConcurrentVector\": \"#34A853\",  # green\n    }\n\n    for i, lib in enumerate(libraries):\n        lib_df = suite_df[suite_df[\"lib\"] == lib]\n        values = []\n        for op in operations:\n            op_df = lib_df[lib_df[\"operation\"] == op]\n            if not op_df.empty:\n                values.append(op_df[\"real_time\"].iloc[0])\n            else:\n                values.append(0)\n\n        values = np.array(values)\n        color = lib_colors.get(lib, \"#888888\")\n        ax.barh(\n            y + i * height - height * num_libs / 2 + height / 2,\n            values,\n            height,\n            label=lib,\n            color=color,\n        )\n\n    ax.set_yticks(y)\n    ax.set_yticklabels(operations, fontsize=10)\n    ax.set_xscale(\"log\")\n    ax.set_xlabel(\"Time (ns) - log scale\", fontsize=12)\n    ax.set_title(title, fontsize=14)\n    ax.legend(loc=\"upper right\", fontsize=10)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{chart_name}.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    return chart_path\n\n\ndef generate_concurrent_vector_charts(\n    df: \"pd.DataFrame\", output_dir: Path, suffix: str = \"\"\n):\n    \"\"\"Generate specialized charts for concurrent_vector benchmarks.\n\n    Args:\n        df: DataFrame with benchmark data\n        output_dir: Output directory for charts\n        suffix: Optional suffix for chart names (e.g., \"_tcmalloc\")\n    \"\"\"\n    # Define operation categories\n    serial_ops = [\n        \"push_back_serial\",\n        \"push_back_serial_reserve\",\n        \"iterate\",\n        \"iterate_reverse\",\n        \"lower_bound\",\n        \"index\",\n        \"random\",\n    ]\n    parallel_ops = [\n        \"parallel\",\n        \"parallel_reserve\",\n        \"parallel_clear\",\n        \"parallel_grow_by_10\",\n        \"parallel_grow_by_100\",\n        \"parallel_grow_by_max\",\n    ]\n\n    # More precise filtering\n    def get_operation(name):\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        for prefix in [\"std_\", \"deque_\", \"tbb_\", \"dispenso_\"]:\n            if clean.startswith(prefix):\n                return clean[len(prefix) :]\n        return clean\n\n    df_with_op = df.copy()\n    df_with_op[\"operation\"] = df_with_op[\"name\"].apply(get_operation)\n\n    serial_df = df_with_op[df_with_op[\"operation\"].isin(serial_ops)]\n    parallel_df = df_with_op[df_with_op[\"operation\"].isin(parallel_ops)]\n\n    # Title suffix for tcmalloc variant\n    title_suffix = \" (tcmalloc)\" if suffix else \"\"\n\n    charts = []\n\n    if not serial_df.empty:\n        chart = generate_horizontal_grouped_bar_chart(\n            f\"Concurrent Vector - Serial/Access Operations{title_suffix}\",\n            serial_df,\n            output_dir,\n            f\"concurrent_vector_serial{suffix}_chart\",\n        )\n        charts.append(chart)\n        print(f\"Generated: {chart}\")\n\n    if not parallel_df.empty:\n        chart = generate_horizontal_grouped_bar_chart(\n            f\"Concurrent Vector - Parallel Operations{title_suffix}\",\n            parallel_df,\n            output_dir,\n            f\"concurrent_vector_parallel{suffix}_chart\",\n        )\n        charts.append(chart)\n        print(f\"Generated: {chart}\")\n\n    return charts\n\n\ndef generate_simple_for_charts(\n    suite_df: \"pd.DataFrame\", output_dir: Path, suite: str = \"simple_for\"\n):\n    \"\"\"Generate specialized charts for simple_for/summing_for/trivial_compute benchmarks.\n\n    - Filters out auto_chunk and static_chunk variants (just uses 'dispenso')\n    - Creates zoomed charts focused on competitive range\n    - No max_threads comparison chart\n    \"\"\"\n\n    # Filter out auto_chunk and static_chunk - just keep base dispenso\n    def should_keep(lib):\n        lib_lower = lib.lower()\n        if \"auto\" in lib_lower or \"static\" in lib_lower:\n            return False\n        return True\n\n    suite_df = suite_df[suite_df[\"library\"].apply(should_keep)].copy()\n\n    worksizes = suite_df[\"worksize\"].dropna().unique()\n    charts = []\n\n    for worksize in sorted(\n        worksizes,\n        key=lambda x: (not str(x).isdigit(), int(x) if str(x).isdigit() else 0),\n    ):\n        ws_df = suite_df[suite_df[\"worksize\"] == worksize].copy()\n        if ws_df.empty:\n            continue\n\n        # Format worksize for title\n        ws_display = worksize\n        if str(worksize).isdigit():\n            ws_int = int(worksize)\n            if ws_int >= 1000000000:\n                ws_display = f\"{ws_int // 1000000000}B\"\n            elif ws_int >= 1000000:\n                ws_display = f\"{ws_int // 1000000}M\"\n            elif ws_int >= 1000:\n                ws_display = f\"{ws_int // 1000}K\"\n\n        # Generate main chart\n        fig, ax = plt.subplots(figsize=(12, 8))\n\n        # Determine appropriate time units for this worksize\n        original_unit = ws_df[\"time_unit\"].iloc[0]\n        scale, display_unit = get_time_scale(ws_df[\"real_time\"].values, original_unit)\n\n        libraries = sorted(ws_df[\"library\"].unique())\n        has_data = False\n        for lib in libraries:\n            lib_df = ws_df[ws_df[\"library\"] == lib].sort_values(\"threads\")\n            if not lib_df.empty and lib_df[\"threads\"].notna().any():\n                label = lib.replace(\"BM_\", \"\").replace(\"_\", \" \")\n                color = get_library_color(label)\n                ax.plot(\n                    lib_df[\"threads\"],\n                    lib_df[\"real_time\"] / scale,\n                    marker=\"o\",\n                    label=label,\n                    color=color,\n                    linewidth=2,\n                    markersize=6,\n                )\n                has_data = True\n\n        if not has_data:\n            plt.close()\n            continue\n\n        suite_display = suite.replace(\"_\", \" \").title()\n        ax.set_xlabel(\"Threads\", fontsize=12)\n        ax.set_ylabel(f\"Time ({display_unit})\", fontsize=12)\n        ax.set_title(f\"{suite_display} - {ws_display} Elements\", fontsize=14)\n        ax.grid(True, alpha=0.3)\n        ax.tick_params(axis=\"both\", labelsize=10)\n        ax.legend(\n            loc=\"upper center\",\n            bbox_to_anchor=(0.5, -0.08),\n            ncol=min(5, len(libraries)),\n            fontsize=11,\n        )\n\n        plt.tight_layout()\n        chart_path = output_dir / f\"{suite}_{worksize}_chart.png\"\n        plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n        plt.close()\n        charts.append(chart_path)\n        print(f\"Generated: {chart_path}\")\n\n        # Generate zoomed chart focusing on competitive libraries (dispenso, tbb, omp)\n        # Find the max value among competitive libraries to set appropriate y-limit\n        competitive_libs = [\"BM_dispenso\", \"BM_tbb\", \"BM_omp\"]\n        competitive_df = ws_df[ws_df[\"library\"].isin(competitive_libs)]\n\n        if not competitive_df.empty and len(competitive_df[\"library\"].unique()) > 1:\n            fig, ax = plt.subplots(figsize=(12, 8))\n\n            # Determine y-limit: use values from mid-range thread counts\n            # Use data-driven percentile-based range, zoom aggressively\n            thread_min = competitive_df[\"threads\"].quantile(0.25)\n            thread_max = competitive_df[\"threads\"].quantile(0.75)\n            mid_thread_df = competitive_df[\n                (competitive_df[\"threads\"] >= thread_min)\n                & (competitive_df[\"threads\"] <= thread_max)\n            ]\n            if not mid_thread_df.empty:\n                # Use 1.5x for tight zoom that focuses on competitive differences\n                y_max = (mid_thread_df[\"real_time\"].max() * 1.5) / scale\n            else:\n                # Fallback: use median-based limit\n                y_max = (competitive_df[\"real_time\"].median() * 2) / scale\n\n            for lib in libraries:\n                lib_df = ws_df[ws_df[\"library\"] == lib].sort_values(\"threads\")\n                if not lib_df.empty and lib_df[\"threads\"].notna().any():\n                    label = lib.replace(\"BM_\", \"\").replace(\"_\", \" \")\n                    color = get_library_color(label)\n                    ax.plot(\n                        lib_df[\"threads\"],\n                        lib_df[\"real_time\"] / scale,\n                        marker=\"o\",\n                        label=label,\n                        color=color,\n                        linewidth=2,\n                        markersize=6,\n                    )\n\n            # Only zoom y-axis, keep full x-axis range to show divergence\n            ax.set_ylim(0, y_max)\n            ax.set_xlabel(\"Threads\", fontsize=12)\n            ax.set_ylabel(f\"Time ({display_unit})\", fontsize=12)\n            ax.set_title(\n                f\"{suite_display} - {ws_display} Elements (Y-Axis Zoomed)\", fontsize=14\n            )\n            ax.grid(True, alpha=0.3)\n            ax.tick_params(axis=\"both\", labelsize=10)\n            ax.legend(\n                loc=\"upper center\",\n                bbox_to_anchor=(0.5, -0.08),\n                ncol=min(5, len(libraries)),\n                fontsize=11,\n            )\n\n            plt.tight_layout()\n            chart_path = output_dir / f\"{suite}_{worksize}_zoomed_chart.png\"\n            plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n            plt.close()\n            charts.append(chart_path)\n            print(f\"Generated: {chart_path}\")\n\n    return charts\n\n\ndef _parse_future_benchmark(name: str):\n    \"\"\"Parse future benchmark name into (implementation, size).\"\"\"\n    clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n\n    # Extract size\n    size = None\n    for sz in [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\"]:\n        if sz in clean:\n            size = sz.replace(\"k\", \"\").replace(\"Size\", \"\")  # \"Small\", \"Medium\", \"Large\"\n            clean = clean.replace(f\"<{sz}>\", \"\")\n            break\n\n    # Map implementation names\n    impl_map = {\n        \"serial_tree\": \"serial\",\n        \"std_tree\": \"std::async\",\n        \"folly_tree\": \"folly::Future\",\n        \"dispenso_tree\": \"dispenso::Future\",\n        \"dispenso_tree_when_all\": \"dispenso::when_all\",\n        \"dispenso_taskset_tree\": \"dispenso::TaskSet\",\n        \"dispenso_taskset_tree_bulk\": \"dispenso::TaskSet (bulk)\",\n    }\n\n    impl = impl_map.get(clean, clean.replace(\"_\", \" \"))\n    return impl, size\n\n\ndef _format_time_value(val_ns):\n    \"\"\"Format time value in appropriate units.\"\"\"\n    if val_ns >= 1e9:\n        return f\"{val_ns / 1e9:.1f}s\"\n    elif val_ns >= 1e6:\n        return f\"{val_ns / 1e6:.1f}ms\"\n    elif val_ns >= 1e3:\n        return f\"{val_ns / 1e3:.0f}µs\"\n    else:\n        return f\"{val_ns:.0f}ns\"\n\n\n# Colors for future benchmark implementations\n_FUTURE_IMPL_COLORS = {\n    \"serial\": \"#95a5a6\",  # Gray\n    \"std::async\": \"#e74c3c\",  # Red\n    \"folly::Future\": \"#e67e22\",  # Orange\n    \"dispenso::Future\": \"#3498db\",  # Blue\n    \"dispenso::TaskSet\": \"#2ecc71\",  # Green\n    \"dispenso::TaskSet (bulk)\": \"#1e8449\",  # Dark green\n    \"dispenso::when_all\": \"#9b59b6\",  # Purple\n}\n\n\ndef _add_future_bar_value_labels(ax, all_bars, all_values, y_max):\n    \"\"\"Add value labels on bars for zoomed future charts.\"\"\"\n    for bars, values in zip(all_bars, all_values):\n        for bar, val in zip(bars, values):\n            if val > 0:\n                label = _format_time_value(val)\n                bar_center_x = bar.get_x() + bar.get_width() / 2\n                if val > y_max:\n                    ax.text(\n                        bar_center_x,\n                        y_max * 0.95,\n                        label,\n                        ha=\"center\",\n                        va=\"top\",\n                        fontsize=7,\n                        color=\"white\",\n                        fontweight=\"bold\",\n                    )\n                else:\n                    ax.text(\n                        bar_center_x,\n                        bar.get_height() + y_max * 0.01,\n                        label,\n                        ha=\"center\",\n                        va=\"bottom\",\n                        fontsize=7,\n                    )\n\n\ndef _render_future_bar_chart(\n    suite_df: \"pd.DataFrame\",\n    implementations: list,\n    sizes: list,\n    output_dir: Path,\n    chart_name: str,\n    title: str,\n    y_max=None,\n    show_value_labels: bool = False,\n) -> Path:\n    \"\"\"Render a grouped bar chart for future benchmark results.\n\n    Args:\n        y_max: If set, clip y-axis at this value (for zoomed charts).\n        show_value_labels: If True, add value labels on bars.\n    \"\"\"\n    import numpy as np\n\n    num_impls = len(implementations)\n    num_sizes = len(sizes)\n    fig, ax = plt.subplots(figsize=(14, 8))\n\n    x = np.arange(num_sizes)\n    width = 0.8 / num_impls\n\n    max_val = 0\n    dnf_positions = []\n    all_bars = []\n    all_values = []\n\n    for i, impl in enumerate(implementations):\n        impl_df = suite_df[suite_df[\"implementation\"] == impl]\n        values = []\n        for size in sizes:\n            size_df = impl_df[impl_df[\"size\"] == size]\n            values.append(size_df[\"real_time\"].iloc[0] if not size_df.empty else 0)\n\n        values = np.array(values)\n        if values.max() > 0:\n            max_val = max(max_val, values.max())\n        color = _FUTURE_IMPL_COLORS.get(impl, \"#888888\")\n        bar_x = x + i * width - width * num_impls / 2 + width / 2\n        bars = ax.bar(bar_x, values, width, label=impl, color=color)\n        all_bars.append(bars)\n        all_values.append(values)\n\n        # Track zero-value positions for \"DID NOT FINISH\" labels\n        for j, val in enumerate(values):\n            if val == 0 and not impl_df.empty:\n                dnf_positions.append((bar_x[j], impl))\n\n    # Draw \"DID NOT FINISH\" labels\n    ref_max = y_max if y_max is not None else max_val\n    for bar_x_pos, impl in dnf_positions:\n        ax.text(\n            bar_x_pos,\n            ref_max * 0.02,\n            \"DID NOT\\nFINISH\",\n            ha=\"center\",\n            va=\"bottom\",\n            fontsize=7,\n            rotation=90,\n            color=_FUTURE_IMPL_COLORS.get(impl, \"#888888\"),\n            fontweight=\"bold\",\n            fontstyle=\"italic\",\n        )\n\n    # Add value labels on the zoomed chart\n    if show_value_labels and y_max is not None:\n        _add_future_bar_value_labels(ax, all_bars, all_values, y_max)\n\n    ax.set_xticks(x)\n    ax.set_xticklabels(sizes, fontsize=12)\n    ax.set_xlabel(\"Tree Size\", fontsize=12)\n    if y_max is not None:\n        ax.set_ylim(0, y_max)\n\n    # Set y-axis label with appropriate time units\n    time_unit = suite_df[\"time_unit\"].iloc[0]\n    effective_max = y_max if y_max is not None else max_val\n    scale, display_unit = get_time_scale([effective_max], time_unit)\n    ax.set_ylabel(f\"Time ({display_unit})\", fontsize=12)\n    if scale != 1:\n        fmt_str = \".2f\" if y_max is not None and display_unit == \"s\" else \".1f\"\n        ax.yaxis.set_major_formatter(\n            plt.FuncFormatter(lambda x, p, s=scale, f=fmt_str: f\"{x / s:{f}}\")\n        )\n\n    ax.set_title(title, fontsize=14)\n    ax.legend(title=\"Implementation\", loc=\"upper left\", fontsize=10)\n    ax.grid(axis=\"y\", alpha=0.3)\n    ax.tick_params(axis=\"y\", labelsize=10)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{chart_name}.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n    return chart_path\n\n\ndef generate_future_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate grouped bar chart for future benchmark.\n\n    X-axis: Tree size (Small, Medium, Large)\n    Grouped bars by implementation (serial, std::async, folly, dispenso variants)\n    \"\"\"\n    suite_df = suite_df.copy()\n    parsed = suite_df[\"name\"].apply(_parse_future_benchmark)\n    suite_df[\"implementation\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"size\"] = parsed.apply(lambda x: x[1])\n\n    suite_df = suite_df[suite_df[\"size\"].notna()]\n    if suite_df.empty:\n        return []\n\n    # Order implementations logically\n    impl_order = [\n        \"serial\",\n        \"std::async\",\n        \"folly::Future\",\n        \"dispenso::Future\",\n        \"dispenso::TaskSet\",\n        \"dispenso::TaskSet (bulk)\",\n        \"dispenso::when_all\",\n    ]\n    implementations = [i for i in impl_order if i in suite_df[\"implementation\"].values]\n    for impl in suite_df[\"implementation\"].unique():\n        if impl not in implementations:\n            implementations.append(impl)\n\n    sizes = [s for s in [\"Small\", \"Medium\", \"Large\"] if s in suite_df[\"size\"].values]\n\n    # Main chart (full scale)\n    charts = [\n        _render_future_bar_chart(\n            suite_df,\n            implementations,\n            sizes,\n            output_dir,\n            \"future_chart\",\n            \"Future/Async Tree Build Benchmark\",\n        )\n    ]\n\n    # Zoomed chart - clip y-axis to focus on competitive range\n    if len(implementations) > 1:\n        dispenso_impls = [\n            i for i in implementations if i.startswith(\"dispenso\") or i == \"serial\"\n        ]\n        dispenso_df = suite_df[suite_df[\"implementation\"].isin(dispenso_impls)]\n        if not dispenso_df.empty:\n            y_max = dispenso_df[\"real_time\"].max() * 1.5\n        else:\n            y_max = suite_df[\"real_time\"].median() * 2\n\n        charts.append(\n            _render_future_bar_chart(\n                suite_df,\n                implementations,\n                sizes,\n                output_dir,\n                \"future_zoomed_chart\",\n                \"Future/Async Tree Build (Y-Axis Zoomed)\",\n                y_max=y_max,\n                show_value_labels=True,\n            )\n        )\n\n    return charts\n\n\ndef generate_graph_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate horizontal bar chart for graph benchmark with logical grouping.\"\"\"\n    import numpy as np\n\n    # Parse and clean benchmark names\n    def parse_graph_name(name: str):\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        # Simplify template names\n        clean = clean.replace(\"<dispenso::BiPropGraph>\", \" (BiProp)\")\n        clean = clean.replace(\"<dispenso::Graph>\", \" (Graph)\")\n        clean = clean.replace(\"_\", \" \")\n        return clean\n\n    suite_df = suite_df.copy()\n    suite_df[\"display_name\"] = suite_df[\"name\"].apply(parse_graph_name)\n\n    # Define logical grouping order\n    group_order = [\n        # Build big tree - taskflow vs dispenso\n        \"taskflow build big tree\",\n        \"build big tree (Graph)\",\n        \"build big tree (BiProp)\",\n        # Dependency chain operations\n        \"build bi prop dependency chain\",\n        \"build bi prop dependency group\",\n        \"build dependency chain (Graph)\",\n        \"build dependency chain (BiProp)\",\n        # Execute operations\n        \"execute dependency chain (Graph)\",\n        \"execute dependency chain (BiProp)\",\n        # Forward propagator\n        \"forward propagator node (Graph)\",\n        \"forward propagator node (BiProp)\",\n    ]\n\n    # Sort by group order\n    def sort_key(name):\n        try:\n            return group_order.index(name)\n        except ValueError:\n            return len(group_order)\n\n    suite_df[\"sort_order\"] = suite_df[\"display_name\"].apply(sort_key)\n    suite_df = suite_df.sort_values(\"sort_order\")\n\n    # Create horizontal bar chart\n    fig, ax = plt.subplots(figsize=(12, 8))\n\n    y = np.arange(len(suite_df))\n    values = suite_df[\"real_time\"].values\n    labels = suite_df[\"display_name\"].values\n\n    # Color by type\n    colors = []\n    for name in labels:\n        if \"taskflow\" in name.lower():\n            colors.append(\"#f39c12\")  # Orange for taskflow\n        elif \"BiProp\" in name:\n            colors.append(\"#27ae60\")  # Darker green for BiProp\n        else:\n            colors.append(\"#2ecc71\")  # Green for dispenso Graph\n\n    bars = ax.barh(y, values, color=colors)\n\n    ax.set_yticks(y)\n    ax.set_yticklabels(labels, fontsize=10)\n\n    # Convert units if needed\n    max_val = values.max()\n    time_unit = suite_df[\"time_unit\"].iloc[0]\n    if time_unit == \"ns\" and max_val >= 1e6:\n        ax.set_xlabel(\"Time (ms)\", fontsize=12)\n        ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f\"{x / 1e6:.1f}\"))\n    elif time_unit == \"ns\" and max_val >= 1e3:\n        ax.set_xlabel(\"Time (µs)\", fontsize=12)\n        ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f\"{x / 1e3:.0f}\"))\n    else:\n        ax.set_xlabel(f\"Time ({time_unit})\", fontsize=12)\n\n    ax.set_title(\"Graph Benchmark Results\", fontsize=14)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    # Add value labels\n    for bar, val in zip(bars, values):\n        if time_unit == \"ns\" and max_val >= 1e6:\n            label = f\"{val / 1e6:.2f}\"\n        elif time_unit == \"ns\" and max_val >= 1e3:\n            label = f\"{val / 1e3:.0f}\"\n        else:\n            label = f\"{val:.0f}\"\n        ax.text(\n            bar.get_width(),\n            bar.get_y() + bar.get_height() / 2,\n            f\" {label}\",\n            va=\"center\",\n            fontsize=9,\n        )\n\n    plt.tight_layout()\n    chart_path = output_dir / \"graph_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n\n    return [chart_path]\n\n\ndef _clean_allocator_name(name):\n    \"\"\"Clean up allocator benchmark display names.\"\"\"\n    clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n    clean = clean.replace(\"<kSmallSize>\", \"[S]\")\n    clean = clean.replace(\"<kMediumSize>\", \"[M]\")\n    clean = clean.replace(\"<kLargeSize>\", \"[L]\")\n    clean = clean.replace(\"<kSmallSize,\", \"[S,\")\n    clean = clean.replace(\"<kMediumSize,\", \"[M,\")\n    clean = clean.replace(\"<kLargeSize,\", \"[L,\")\n    clean = clean.replace(\">\", \"]\")\n    clean = clean.replace(\"_\", \" \")\n    return clean\n\n\ndef _generate_small_buffer_charts(suite_df: \"pd.DataFrame\", output_dir: Path) -> list:\n    \"\"\"Generate horizontal bar chart for small_buffer benchmark.\"\"\"\n    import numpy as np\n\n    suite_df = suite_df.copy()\n    suite_df[\"display_name\"] = suite_df[\"name\"].apply(_clean_allocator_name)\n\n    def parse_small_buffer_name(name):\n        if \"[S]\" in name:\n            size, size_label = 0, \"S\"\n        elif \"[M]\" in name:\n            size, size_label = 1, \"M\"\n        elif \"[L]\" in name:\n            size, size_label = 2, \"L\"\n        else:\n            size, size_label = 3, \"?\"\n\n        iter_match = re.search(r\"/(\\d+)\", name)\n        iterations = int(iter_match.group(1)) if iter_match else 0\n        thread_match = re.search(r\"threads:(\\d+)\", name)\n        threads = int(thread_match.group(1)) if thread_match else 1\n        is_small_buffer = \"small buffer\" in name.lower()\n        return size, iterations, threads, is_small_buffer, size_label\n\n    parsed = suite_df[\"display_name\"].apply(parse_small_buffer_name)\n    suite_df[\"size_order\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"iterations\"] = parsed.apply(lambda x: x[1])\n    suite_df[\"threads\"] = parsed.apply(lambda x: x[2])\n    suite_df[\"is_small_buffer\"] = parsed.apply(lambda x: x[3])\n\n    suite_df = suite_df.sort_values(\n        [\"size_order\", \"iterations\", \"threads\", \"is_small_buffer\"]\n    )\n\n    fig, ax = plt.subplots(figsize=(14, max(8, len(suite_df) * 0.35)))\n    y = np.arange(len(suite_df))\n    values = suite_df[\"real_time\"].values.copy()\n    labels = suite_df[\"display_name\"].values\n\n    # Detect outliers using 90th percentile and clip\n    threshold = np.percentile(values, 90)\n    clipped_values = np.minimum(values, threshold * 1.1)\n    outlier_mask = values > threshold\n\n    colors = [\n        \"#2ecc71\" if is_sb else \"#e74c3c\" for is_sb in suite_df[\"is_small_buffer\"]\n    ]\n\n    bars = ax.barh(y, clipped_values, color=colors)\n    ax.set_yticks(y)\n    ax.set_yticklabels(labels, fontsize=8)\n\n    # Add outlier annotations\n    for i, (is_outlier, orig_val) in enumerate(zip(outlier_mask, values)):\n        if is_outlier:\n            label = f\"({_format_time_value(orig_val)})\"\n            ax.text(\n                clipped_values[i],\n                i,\n                f\" {label}\",\n                va=\"center\",\n                fontsize=7,\n                style=\"italic\",\n            )\n\n    time_unit = suite_df[\"time_unit\"].iloc[0]\n    scale, display_unit = get_time_scale(clipped_values, time_unit)\n    ax.set_xlabel(f\"Time ({display_unit})\", fontsize=12)\n    if scale != 1:\n        ax.xaxis.set_major_formatter(\n            plt.FuncFormatter(lambda x, p, s=scale: f\"{x / s:.1f}\")\n        )\n\n    ax.set_title(\"Small Buffer Allocator Benchmark\", fontsize=14)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    from matplotlib.patches import Patch\n\n    legend_elements = [\n        Patch(facecolor=\"#2ecc71\", label=\"SmallBufferAllocator\"),\n        Patch(facecolor=\"#e74c3c\", label=\"new/delete\"),\n    ]\n    ax.legend(handles=legend_elements, loc=\"lower right\", fontsize=9)\n\n    plt.tight_layout()\n    chart_path = output_dir / \"small_buffer_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n    return [chart_path]\n\n\ndef _generate_pool_allocator_split_charts(\n    suite_df: \"pd.DataFrame\", output_dir: Path\n) -> list:\n    \"\"\"Generate split fast/slow horizontal bar charts for pool_allocator benchmark.\"\"\"\n    import numpy as np\n\n    suite_df = suite_df.copy()\n    suite_df[\"display_name\"] = suite_df[\"name\"].apply(_clean_allocator_name)\n\n    charts = []\n    threshold = suite_df[\"real_time\"].median()\n\n    for group_name, group_df in [\n        (\"fast\", suite_df[suite_df[\"real_time\"] < threshold]),\n        (\"slow\", suite_df[suite_df[\"real_time\"] >= threshold]),\n    ]:\n        if group_df.empty:\n            continue\n\n        group_df = group_df.sort_values(\"real_time\")\n\n        fig, ax = plt.subplots(figsize=(12, max(6, len(group_df) * 0.35)))\n        y = np.arange(len(group_df))\n        values = group_df[\"real_time\"].values\n        labels = group_df[\"display_name\"].values\n\n        colors = []\n        for name in labels:\n            name_lower = name.lower()\n            if \"malloc\" in name_lower:\n                colors.append(\"#e74c3c\")\n            elif \"arena\" in name_lower:\n                colors.append(\"#2ecc71\")\n            elif \"nl pool\" in name_lower:\n                colors.append(\"#3498db\")\n            else:\n                colors.append(\"#9b59b6\")\n\n        ax.barh(y, values, color=colors)\n        ax.set_yticks(y)\n        ax.set_yticklabels(labels, fontsize=8)\n\n        max_val = values.max()\n        time_unit = group_df[\"time_unit\"].iloc[0]\n        scale, display_unit = get_time_scale([max_val], time_unit)\n        ax.set_xlabel(f\"Time ({display_unit})\", fontsize=12)\n        if scale != 1:\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p, s=scale: f\"{x / s:.1f}\")\n            )\n\n        title_suffix = \"Fast Operations\" if group_name == \"fast\" else \"Slow Operations\"\n        ax.set_title(f\"Pool Allocator - {title_suffix}\", fontsize=14)\n        ax.grid(axis=\"x\", alpha=0.3)\n\n        plt.tight_layout()\n        chart_path = output_dir / f\"pool_allocator_{group_name}_chart.png\"\n        plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n        plt.close()\n        charts.append(chart_path)\n        print(f\"Generated: {chart_path}\")\n\n    return charts\n\n\ndef generate_allocator_charts(suite_df: \"pd.DataFrame\", output_dir: Path, suite: str):\n    \"\"\"Generate horizontal bar charts for pool_allocator and small_buffer benchmarks.\"\"\"\n    if suite == \"small_buffer\":\n        return _generate_small_buffer_charts(suite_df, output_dir)\n    elif suite == \"pool_allocator\":\n        return _generate_pool_allocator_split_charts(suite_df, output_dir)\n    return []\n\n\ndef _parse_rw_lock_name(name: str):\n    \"\"\"Parse rw_lock benchmark name into (operation, mutex, threads, contention).\"\"\"\n    clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n\n    mutex = None\n    for m in [\"NopMutex\", \"std::shared_mutex\", \"dispenso::RWLock\"]:\n        if m in clean:\n            mutex = m\n            clean = clean.replace(f\"<{m}>\", \"\")\n            break\n\n    parts = clean.split(\"/\")\n    operation = parts[0]\n\n    if operation == \"serial\":\n        threads = None\n        contention = parts[1] if len(parts) > 1 else None\n    else:\n        threads = parts[1] if len(parts) > 1 else None\n        contention = parts[2] if len(parts) > 2 else None\n\n    return operation, mutex, threads, contention\n\n\ndef _render_rw_lock_parallel_chart(\n    cont_df: \"pd.DataFrame\",\n    cont: str,\n    available_mutexes: list,\n    thread_counts: list,\n    colors: dict,\n    output_dir: Path,\n) -> Path:\n    \"\"\"Render a single rw_lock parallel chart for a given contention level.\"\"\"\n    import numpy as np\n\n    fig, ax = plt.subplots(figsize=(10, 5))\n\n    y = np.arange(len(thread_counts))\n    height = 0.8 / len(available_mutexes)\n\n    max_val = 0\n    for i, mutex in enumerate(available_mutexes):\n        values = []\n        for threads in thread_counts:\n            row = cont_df[(cont_df[\"mutex\"] == mutex) & (cont_df[\"threads\"] == threads)]\n            values.append(row[\"real_time\"].iloc[0] if not row.empty else 0)\n        values = np.array(values)\n        max_val = max(max_val, values.max())\n        ax.barh(\n            y + i * height - height * len(available_mutexes) / 2 + height / 2,\n            values,\n            height,\n            label=mutex,\n            color=colors.get(mutex, \"#3498db\"),\n        )\n\n    ax.set_yticks(y)\n    ax.set_yticklabels([f\"{t} threads\" for t in thread_counts], fontsize=10)\n\n    scale, display_unit = get_time_scale([max_val], \"ns\")\n    ax.set_xlabel(f\"Time ({display_unit})\", fontsize=12)\n    if scale != 1:\n        ax.xaxis.set_major_formatter(\n            plt.FuncFormatter(lambda x, p, s=scale: f\"{x / s:.0f}\")\n        )\n\n    ax.set_title(f\"RW Lock - Parallel ({cont} iterations)\", fontsize=14)\n    ax.legend(loc=\"upper right\", fontsize=9)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"rw_lock_parallel_{cont}_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n    return chart_path\n\n\ndef generate_rw_lock_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate horizontal grouped bar charts for rw_lock benchmark.\"\"\"\n    import numpy as np\n\n    suite_df = suite_df.copy()\n    parsed = suite_df[\"name\"].apply(_parse_rw_lock_name)\n    suite_df[\"operation\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"mutex\"] = parsed.apply(lambda x: x[1])\n    suite_df[\"threads\"] = parsed.apply(lambda x: x[2])\n    suite_df[\"contention\"] = parsed.apply(lambda x: x[3])\n\n    charts = []\n    mutexes = [\"NopMutex\", \"std::shared_mutex\", \"dispenso::RWLock\"]\n    colors = {\n        \"NopMutex\": \"#95a5a6\",\n        \"std::shared_mutex\": \"#e74c3c\",\n        \"dispenso::RWLock\": \"#2ecc71\",\n    }\n\n    # Serial chart\n    serial_df = suite_df[suite_df[\"operation\"] == \"serial\"]\n    if not serial_df.empty:\n        available_mutexes = [m for m in mutexes if m in serial_df[\"mutex\"].values]\n        contentions = sorted(\n            serial_df[\"contention\"].dropna().unique(), key=lambda x: int(x)\n        )\n\n        if available_mutexes and contentions:\n            fig, ax = plt.subplots(figsize=(10, 5))\n\n            y = np.arange(len(contentions))\n            height = 0.8 / len(available_mutexes)\n\n            for i, mutex in enumerate(available_mutexes):\n                values = []\n                for cont in contentions:\n                    row = serial_df[\n                        (serial_df[\"mutex\"] == mutex)\n                        & (serial_df[\"contention\"] == cont)\n                    ]\n                    values.append(row[\"real_time\"].iloc[0] if not row.empty else 0)\n                values = np.array(values)\n                ax.barh(\n                    y + i * height - height * len(available_mutexes) / 2 + height / 2,\n                    values,\n                    height,\n                    label=mutex,\n                    color=colors.get(mutex, \"#3498db\"),\n                )\n\n            ax.set_yticks(y)\n            ax.set_yticklabels([f\"{c} iterations\" for c in contentions], fontsize=10)\n            ax.set_xlabel(\"Time (ms)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e6:.1f}\")\n            )\n            ax.set_title(\"RW Lock - Serial Operations\", fontsize=14)\n            ax.legend(loc=\"upper right\", fontsize=9)\n            ax.grid(axis=\"x\", alpha=0.3)\n\n            plt.tight_layout()\n            chart_path = output_dir / \"rw_lock_serial_chart.png\"\n            plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n            plt.close()\n            charts.append(chart_path)\n            print(f\"Generated: {chart_path}\")\n\n    # Parallel charts - one per contention level\n    parallel_df = suite_df[suite_df[\"operation\"] == \"parallel\"]\n    if not parallel_df.empty:\n        available_mutexes = [m for m in mutexes if m in parallel_df[\"mutex\"].values]\n        available_mutexes = [m for m in available_mutexes if m != \"NopMutex\"]\n        contentions = sorted(\n            parallel_df[\"contention\"].dropna().unique(), key=lambda x: int(x)\n        )\n        thread_counts = sorted(\n            parallel_df[\"threads\"].dropna().unique(), key=lambda x: int(x)\n        )\n\n        for cont in contentions:\n            cont_df = parallel_df[parallel_df[\"contention\"] == cont]\n            if not cont_df.empty:\n                chart_path = _render_rw_lock_parallel_chart(\n                    cont_df, cont, available_mutexes, thread_counts, colors, output_dir\n                )\n                charts.append(chart_path)\n\n    return charts\n\n\ndef generate_once_function_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate horizontal bar charts for once_function benchmark.\n\n    Split into move vs queue operations, grouped by size.\n    \"\"\"\n    import numpy as np\n\n    # Parse benchmark names\n    def parse_once_function_name(name: str):\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n\n        # Extract operation (move or queue)\n        if clean.startswith(\"move_\"):\n            operation = \"move\"\n            clean = clean[5:]\n        elif clean.startswith(\"queue_\"):\n            operation = \"queue\"\n            clean = clean[6:]\n        else:\n            operation = \"unknown\"\n\n        # Extract function type and size\n        if \"<\" in clean:\n            func_type, size = clean.split(\"<\")\n            size = size.rstrip(\">\")\n        else:\n            func_type = clean\n            size = \"unknown\"\n\n        # Clean up function type name\n        func_type = func_type.replace(\"_\", \" \").title()\n\n        return operation, func_type, size\n\n    suite_df = suite_df.copy()\n    parsed = suite_df[\"name\"].apply(parse_once_function_name)\n    suite_df[\"operation\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"func_type\"] = parsed.apply(lambda x: x[1])\n    suite_df[\"size\"] = parsed.apply(lambda x: x[2])\n\n    charts = []\n    size_order = [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\", \"kExtraLargeSize\"]\n    size_labels = {\n        \"kSmallSize\": \"Small\",\n        \"kMediumSize\": \"Medium\",\n        \"kLargeSize\": \"Large\",\n        \"kExtraLargeSize\": \"Extra Large\",\n    }\n    colors = {\n        \"Std Function\": \"#e74c3c\",\n        \"Once Function\": \"#2ecc71\",\n        \"Inline Function\": \"#3498db\",\n    }\n\n    for op in [\"move\", \"queue\"]:\n        op_df = suite_df[suite_df[\"operation\"] == op]\n        if op_df.empty:\n            continue\n\n        func_types = sorted(op_df[\"func_type\"].unique())\n        sizes = [s for s in size_order if s in op_df[\"size\"].values]\n\n        if not func_types or not sizes:\n            continue\n\n        fig, ax = plt.subplots(figsize=(10, 5))\n\n        y = np.arange(len(sizes))\n        height = 0.8 / len(func_types)\n\n        max_val = 0\n        for i, func_type in enumerate(func_types):\n            values = []\n            for size in sizes:\n                row = op_df[(op_df[\"func_type\"] == func_type) & (op_df[\"size\"] == size)]\n                values.append(row[\"real_time\"].iloc[0] if not row.empty else 0)\n            values = np.array(values)\n            max_val = max(max_val, values.max())\n            ax.barh(\n                y + i * height - height * len(func_types) / 2 + height / 2,\n                values,\n                height,\n                label=func_type,\n                color=colors.get(func_type, \"#9b59b6\"),\n            )\n\n        ax.set_yticks(y)\n        ax.set_yticklabels([size_labels.get(s, s) for s in sizes], fontsize=11)\n\n        # Format time axis\n        if max_val >= 1e6:\n            ax.set_xlabel(\"Time (ms)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e6:.1f}\")\n            )\n        elif max_val >= 1e3:\n            ax.set_xlabel(\"Time (µs)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e3:.1f}\")\n            )\n        else:\n            ax.set_xlabel(\"Time (ns)\", fontsize=12)\n\n        ax.set_title(f\"Once Function - {op.title()} Operations\", fontsize=14)\n        ax.legend(loc=\"upper right\", fontsize=10)\n        ax.grid(axis=\"x\", alpha=0.3)\n\n        plt.tight_layout()\n        chart_path = output_dir / f\"once_function_{op}_chart.png\"\n        plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n        plt.close()\n        charts.append(chart_path)\n        print(f\"Generated: {chart_path}\")\n\n    return charts\n\n\ndef generate_pool_allocator_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate horizontal bar charts for pool_allocator benchmark.\n\n    Split by thread count, grouped by allocator type and size.\n    \"\"\"\n    import numpy as np\n\n    # Parse benchmark names\n    def parse_pool_alloc_name(name: str):\n        clean = name.replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n\n        # Extract allocator type\n        if clean.startswith(\"mallocfree_threaded\"):\n            alloc_type = \"malloc/free\"\n            rest = clean[19:]  # after \"mallocfree_threaded\"\n        elif clean.startswith(\"mallocfree\"):\n            alloc_type = \"malloc/free\"\n            rest = clean[10:]  # after \"mallocfree\"\n        elif clean.startswith(\"nl_pool_allocator_arena\"):\n            alloc_type = \"NoLock Arena\"\n            rest = clean[23:]\n        elif clean.startswith(\"nl_pool_allocator\"):\n            alloc_type = \"NoLock\"\n            rest = clean[17:]\n        elif clean.startswith(\"pool_allocator_arena\"):\n            alloc_type = \"Arena\"\n            rest = clean[20:]\n        elif clean.startswith(\"pool_allocator_threaded\"):\n            alloc_type = \"PoolAllocator\"\n            rest = clean[23:]\n        elif clean.startswith(\"pool_allocator\"):\n            alloc_type = \"PoolAllocator\"\n            rest = clean[14:]\n        else:\n            alloc_type = \"unknown\"\n            rest = clean\n\n        # Parse <Size,Threads>/iterations or <Size>/iterations\n        size = \"unknown\"\n        threads = 1\n        iterations = 0\n\n        if \"<\" in rest:\n            params, iters = rest.split(\">\")\n            params = params.lstrip(\"<\")\n            if \",\" in params:\n                size, threads = params.split(\",\")\n                threads = int(threads)\n            else:\n                size = params\n            if \"/\" in iters:\n                iterations = int(iters.lstrip(\"/\"))\n        elif \"/\" in rest:\n            iterations = int(rest.lstrip(\"/\"))\n\n        return alloc_type, size, threads, iterations\n\n    suite_df = suite_df.copy()\n    parsed = suite_df[\"name\"].apply(parse_pool_alloc_name)\n    suite_df[\"alloc_type\"] = parsed.apply(lambda x: x[0])\n    suite_df[\"size\"] = parsed.apply(lambda x: x[1])\n    suite_df[\"threads\"] = parsed.apply(lambda x: x[2])\n    suite_df[\"iterations\"] = parsed.apply(lambda x: x[3])\n\n    charts = []\n    size_order = [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\"]\n    size_labels = {\"kSmallSize\": \"S\", \"kMediumSize\": \"M\", \"kLargeSize\": \"L\"}\n\n    # Colors for allocator types\n    colors = {\n        \"malloc/free\": \"#e74c3c\",\n        \"PoolAllocator\": \"#2ecc71\",\n        \"Arena\": \"#27ae60\",\n        \"NoLock\": \"#3498db\",\n        \"NoLock Arena\": \"#2980b9\",\n    }\n\n    # Group by thread count\n    thread_counts = sorted(suite_df[\"threads\"].unique())\n\n    for threads in thread_counts:\n        thread_df = suite_df[suite_df[\"threads\"] == threads]\n        if thread_df.empty:\n            continue\n\n        # For single-threaded, show all allocator types\n        # For multi-threaded, show only threaded variants\n        if threads == 1:\n            alloc_types = [\n                \"malloc/free\",\n                \"PoolAllocator\",\n                \"Arena\",\n                \"NoLock\",\n                \"NoLock Arena\",\n            ]\n            title_suffix = \"Single-threaded\"\n        else:\n            alloc_types = [\"malloc/free\", \"PoolAllocator\"]\n            title_suffix = f\"{threads} Threads\"\n\n        alloc_types = [a for a in alloc_types if a in thread_df[\"alloc_type\"].values]\n        iterations_list = sorted(thread_df[\"iterations\"].unique())\n\n        if not alloc_types:\n            continue\n\n        # Create grouped labels: Size x Iterations\n        group_labels = []\n        for size in size_order:\n            for iters in iterations_list:\n                if iters >= 1000:\n                    iters_label = f\"{iters // 1000}K\"\n                else:\n                    iters_label = str(iters)\n                group_labels.append(f\"{size_labels.get(size, size)}/{iters_label}\")\n\n        fig, ax = plt.subplots(figsize=(12, max(6, len(group_labels) * 0.4)))\n\n        y = np.arange(len(group_labels))\n        height = 0.8 / len(alloc_types)\n\n        max_val = 0\n        for i, alloc_type in enumerate(alloc_types):\n            values = []\n            for size in size_order:\n                for iters in iterations_list:\n                    row = thread_df[\n                        (thread_df[\"alloc_type\"] == alloc_type)\n                        & (thread_df[\"size\"] == size)\n                        & (thread_df[\"iterations\"] == iters)\n                    ]\n                    values.append(row[\"real_time\"].iloc[0] if not row.empty else 0)\n            values = np.array(values)\n            max_val = max(max_val, values.max())\n            ax.barh(\n                y + i * height - height * len(alloc_types) / 2 + height / 2,\n                values,\n                height,\n                label=alloc_type,\n                color=colors.get(alloc_type, \"#9b59b6\"),\n            )\n\n        ax.set_yticks(y)\n        ax.set_yticklabels(group_labels, fontsize=10)\n\n        # Format time axis\n        if max_val >= 1e9:\n            ax.set_xlabel(\"Time (s)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e9:.1f}\")\n            )\n        elif max_val >= 1e6:\n            ax.set_xlabel(\"Time (ms)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e6:.0f}\")\n            )\n        elif max_val >= 1e3:\n            ax.set_xlabel(\"Time (µs)\", fontsize=12)\n            ax.xaxis.set_major_formatter(\n                plt.FuncFormatter(lambda x, p: f\"{x / 1e3:.0f}\")\n            )\n        else:\n            ax.set_xlabel(\"Time (ns)\", fontsize=12)\n\n        ax.set_title(f\"Pool Allocator - {title_suffix}\", fontsize=14)\n        ax.legend(loc=\"upper right\", fontsize=9)\n        ax.grid(axis=\"x\", alpha=0.3)\n\n        plt.tight_layout()\n        chart_path = output_dir / f\"pool_allocator_{threads}t_chart.png\"\n        plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n        plt.close()\n        charts.append(chart_path)\n        print(f\"Generated: {chart_path}\")\n\n    return charts\n\n\ndef generate_simple_horizontal_chart(\n    suite_df: \"pd.DataFrame\", output_dir: Path, suite: str\n):\n    \"\"\"Generate a simple horizontal bar chart for a benchmark suite.\"\"\"\n    import numpy as np\n\n    suite_df = suite_df.copy()\n    suite_df[\"display_name\"] = suite_df[\"name\"].apply(\n        lambda x: x.replace(\"BM_\", \"\").replace(\"/real_time\", \"\").replace(\"_\", \" \")\n    )\n    suite_df = suite_df.sort_values(\"real_time\")\n\n    fig, ax = plt.subplots(figsize=(12, max(6, len(suite_df) * 0.5)))\n\n    y = np.arange(len(suite_df))\n    values = suite_df[\"real_time\"].values\n    labels = suite_df[\"display_name\"].values\n\n    bars = ax.barh(y, values, color=\"#3498db\")\n    ax.set_yticks(y)\n    ax.set_yticklabels(labels, fontsize=10)\n\n    max_val = values.max()\n    time_unit = suite_df[\"time_unit\"].iloc[0]\n    if time_unit == \"ns\" and max_val >= 1e6:\n        ax.set_xlabel(\"Time (ms)\", fontsize=12)\n        ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f\"{x / 1e6:.1f}\"))\n    elif time_unit == \"ns\" and max_val >= 1e3:\n        ax.set_xlabel(\"Time (µs)\", fontsize=12)\n        ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f\"{x / 1e3:.0f}\"))\n    else:\n        ax.set_xlabel(f\"Time ({time_unit})\", fontsize=12)\n\n    ax.set_title(f\"{suite.replace('_', ' ').title()} Benchmark\", fontsize=14)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    plt.tight_layout()\n    chart_path = output_dir / f\"{suite}_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n\n    return [chart_path]\n\n\ndef _parse_timed_task_row(row):\n    \"\"\"Parse a timed_task benchmark row into a dict with library, config, etc.\n\n    Returns None if the row doesn't have the expected format.\n    \"\"\"\n    name = row[\"name\"]\n    mean_err = row.get(\"mean\", None)\n    stddev_err = row.get(\"stddev\", None)\n\n    if mean_err is None or stddev_err is None:\n        return None\n\n    match = re.match(r\"BM_(\\w+)<(.+)>\", name)\n    if not match:\n        return None\n\n    func_name = match.group(1)\n    template_args = match.group(2).strip()\n\n    if \"mixed\" in func_name:\n        library = func_name.replace(\"_mixed\", \"\")\n        steady = template_args.strip().lower() == \"true\"\n        config_label = f\"Mixed ({'Steady' if steady else 'Normal'})\"\n        period_ms = None\n        is_mixed = True\n    else:\n        library = func_name\n        is_mixed = False\n        parts = [p.strip() for p in template_args.split(\",\")]\n        if len(parts) != 2:\n            return None\n        try:\n            period_ms = int(parts[0])\n        except ValueError:\n            return None\n        steady = parts[1].lower() == \"true\"\n        config_label = f\"{period_ms}ms ({'Steady' if steady else 'Normal'})\"\n\n    return {\n        \"library\": library,\n        \"config\": config_label,\n        \"is_mixed\": is_mixed,\n        \"steady\": steady,\n        \"period_ms\": period_ms,\n        \"mean_error_us\": mean_err * 1e6,\n        \"stddev_us\": stddev_err * 1e6,\n    }\n\n\ndef _build_timed_task_config_order(timed_df: \"pd.DataFrame\") -> list:\n    \"\"\"Build the ordered list of config labels for timed_task charts.\"\"\"\n    config_order = []\n    # Single-period configs sorted by period\n    for steady in [False, True]:\n        for period in sorted(\n            timed_df[~timed_df[\"is_mixed\"]][\"period_ms\"].dropna().unique()\n        ):\n            label = f\"{int(period)}ms ({'Steady' if steady else 'Normal'})\"\n            if label in timed_df[\"config\"].values:\n                config_order.append(label)\n    # Mixed configs\n    for steady in [False, True]:\n        label = f\"Mixed ({'Steady' if steady else 'Normal'})\"\n        if label in timed_df[\"config\"].values:\n            config_order.append(label)\n    return [c for c in config_order if c in timed_df[\"config\"].values]\n\n\ndef generate_timed_task_charts(suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate bar chart of scheduling jitter for timed_task benchmark.\"\"\"\n    import numpy as np\n\n    rows = []\n    for _, row in suite_df.iterrows():\n        parsed = _parse_timed_task_row(row)\n        if parsed is not None:\n            rows.append(parsed)\n\n    if not rows:\n        print(\"  No timed_task data with mean/stddev counters found\")\n        return []\n\n    timed_df = pd.DataFrame(rows)\n    config_order = _build_timed_task_config_order(timed_df)\n\n    libraries = sorted(timed_df[\"library\"].unique())\n    lib_colors = {lib: get_library_color(lib) for lib in libraries}\n\n    fig, ax = plt.subplots(figsize=(12, max(6, len(config_order) * 0.8)))\n\n    y = np.arange(len(config_order))\n    bar_height = 0.8 / len(libraries)\n\n    for i, lib in enumerate(libraries):\n        means = []\n        stddevs = []\n        for config in config_order:\n            row = timed_df[\n                (timed_df[\"library\"] == lib) & (timed_df[\"config\"] == config)\n            ]\n            if not row.empty:\n                means.append(row[\"mean_error_us\"].iloc[0])\n                stddevs.append(row[\"stddev_us\"].iloc[0])\n            else:\n                means.append(0)\n                stddevs.append(0)\n\n        offset = i * bar_height - bar_height * len(libraries) / 2 + bar_height / 2\n        ax.barh(\n            y + offset,\n            means,\n            bar_height,\n            xerr=stddevs,\n            label=lib,\n            color=lib_colors.get(lib, \"#7f8c8d\"),\n            capsize=3,\n            error_kw={\"linewidth\": 1},\n        )\n\n    ax.set_yticks(y)\n    ax.set_yticklabels(config_order, fontsize=10)\n    ax.set_xlabel(\"Mean Scheduling Error (µs)\", fontsize=12)\n    ax.set_title(\"Timed Task Scheduling Jitter\", fontsize=14)\n    ax.legend(loc=\"upper right\", fontsize=10)\n    ax.grid(axis=\"x\", alpha=0.3)\n\n    plt.tight_layout()\n    chart_path = output_dir / \"timed_task_chart.png\"\n    plt.savefig(chart_path, dpi=150, bbox_inches=\"tight\")\n    plt.close()\n    print(f\"Generated: {chart_path}\")\n\n    return [chart_path]\n\n\ndef generate_charts(df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Generate comparison charts from benchmark data.\"\"\"\n    if df.empty:\n        print(\"No data to plot\")\n        return\n\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    # Parse benchmark names to extract structured data\n    parsed = df[\"name\"].apply(parse_benchmark_name)\n    df = df.copy()\n    df[\"library\"] = parsed.apply(lambda x: x[\"library\"])\n    df[\"threads\"] = parsed.apply(lambda x: x[\"threads\"])\n    df[\"worksize\"] = parsed.apply(lambda x: x[\"worksize\"])\n\n    # Suites with specialized chart generation (thread scaling line charts)\n    specialized_thread_scaling = [\n        \"simple_for\",\n        \"summing_for\",\n        \"trivial_compute\",\n        \"nested_for\",\n    ]\n\n    # Group by suite\n    for suite, suite_df in df.groupby(\"suite\"):\n        # Special handling for concurrent_vector suite (and tcmalloc variant)\n        if suite == \"concurrent_vector\":\n            generate_concurrent_vector_charts(suite_df, output_dir)\n            continue\n        if suite == \"concurrent_vector_tcmalloc\":\n            generate_concurrent_vector_charts(suite_df, output_dir, suffix=\"_tcmalloc\")\n            continue\n\n        # Special handling for future benchmark\n        if suite == \"future\":\n            generate_future_charts(suite_df, output_dir)\n            continue\n\n        # Special handling for graph benchmark\n        if suite == \"graph\":\n            generate_graph_charts(suite_df, output_dir)\n            continue\n\n        # Special handling for pool_allocator and small_buffer\n        if suite == \"pool_allocator\":\n            generate_pool_allocator_charts(suite_df, output_dir)\n            continue\n        if suite == \"small_buffer\":\n            generate_allocator_charts(suite_df, output_dir, suite)\n            continue\n\n        # Special handling for rw_lock\n        if suite == \"rw_lock\":\n            generate_rw_lock_charts(suite_df, output_dir)\n            continue\n\n        # Special handling for once_function - split into move/queue charts\n        if suite == \"once_function\":\n            generate_once_function_charts(suite_df, output_dir)\n            continue\n\n        # Timed task: bar chart of scheduling jitter (mean error + stddev)\n        if suite == \"timed_task\":\n            generate_timed_task_charts(suite_df, output_dir)\n            continue\n\n        # Special handling for simple_for, summing_for, trivial_compute\n        if suite in specialized_thread_scaling:\n            generate_simple_for_charts(suite_df, output_dir, suite)\n            continue\n\n        # Determine chart type based on data structure\n        has_thread_data = suite_df[\"threads\"].notna().any()\n        worksizes = suite_df[\"worksize\"].dropna().unique()\n\n        if has_thread_data and len(worksizes) > 0:\n            # Generate line charts for each worksize (no max_threads chart)\n            for worksize in sorted(worksizes, key=lambda x: (str(x).isdigit(), x)):\n                chart_path = generate_line_chart(suite, suite_df, output_dir, worksize)\n                if chart_path:\n                    print(f\"Generated: {chart_path}\")\n        else:\n            # Simple bar chart for benchmarks without thread/worksize structure\n            chart_path = generate_bar_chart(suite, suite_df, output_dir)\n            print(f\"Generated: {chart_path}\")\n\n\ndef _format_worksize(worksize) -> str:\n    \"\"\"Format a numeric worksize for display (e.g., 1000000 -> '1M').\"\"\"\n    if not str(worksize).isdigit():\n        return str(worksize)\n    ws_int = int(worksize)\n    if ws_int >= 1000000000:\n        return f\"{ws_int // 1000000000}B\"\n    elif ws_int >= 1000000:\n        return f\"{ws_int // 1000000}M\"\n    elif ws_int >= 1000:\n        return f\"{ws_int // 1000}K\"\n    return str(ws_int)\n\n\n# Registry mapping suite names to their chart entries.\n# Each entry is (caption, chart_filename) or None for entries that need dynamic generation.\n_SUITE_CHART_REGISTRY = {\n    \"concurrent_vector\": [\n        (\"**Serial/Access Operations:**\", \"concurrent_vector_serial_chart.png\"),\n        (\"**Parallel Operations:**\", \"concurrent_vector_parallel_chart.png\"),\n    ],\n    \"concurrent_vector_tcmalloc\": [\n        (\n            \"**Serial/Access Operations (tcmalloc):**\",\n            \"concurrent_vector_serial_tcmalloc_chart.png\",\n        ),\n        (\n            \"**Parallel Operations (tcmalloc):**\",\n            \"concurrent_vector_parallel_tcmalloc_chart.png\",\n        ),\n    ],\n    \"future\": [\n        (\"**Full comparison (including std::async):**\", \"future_chart.png\"),\n        (\"**Zoomed (excluding std::async):**\", \"future_zoomed_chart.png\"),\n    ],\n    \"graph\": [\n        (None, \"graph_chart.png\"),\n    ],\n    \"small_buffer\": [\n        (None, \"small_buffer_chart.png\"),\n    ],\n    \"pool_allocator\": [\n        (\"**Single-threaded:**\", \"pool_allocator_1t_chart.png\"),\n        (\"**2 Threads:**\", \"pool_allocator_2t_chart.png\"),\n        (\"**8 Threads:**\", \"pool_allocator_8t_chart.png\"),\n        (\"**16 Threads:**\", \"pool_allocator_16t_chart.png\"),\n    ],\n    \"once_function\": [\n        (\"**Move Operations:**\", \"once_function_move_chart.png\"),\n        (\"**Queue Operations:**\", \"once_function_queue_chart.png\"),\n    ],\n    \"rw_lock\": [\n        (\"**Serial Operations:**\", \"rw_lock_serial_chart.png\"),\n        (\"**Parallel Operations:**\", None),  # sentinel for per-contention charts\n    ],\n    \"timed_task\": [\n        (\"**Scheduling Jitter (Mean Error ± Stddev):**\", \"timed_task_chart.png\"),\n    ],\n}\n\n# Suites that use worksize-based thread scaling charts (with zoomed variants)\n_THREAD_SCALING_SUITES = {\"simple_for\", \"summing_for\", \"trivial_compute\", \"nested_for\"}\n\n# RW lock contention levels for parallel sub-charts\n_RW_LOCK_CONTENTIONS = [2, 8, 32, 128, 512]\n\n\ndef _write_suite_detail_table(suite: str, suite_df: \"pd.DataFrame\", output_dir: Path):\n    \"\"\"Write a per-suite detailed results table to a separate markdown file.\"\"\"\n    detail_path = output_dir / f\"{suite}_details.md\"\n    with open(detail_path, \"w\") as detail_f:\n        detail_f.write(f\"# {suite} - Detailed Results\\n\\n\")\n        detail_f.write(\"| Benchmark | Time | Unit | Iterations |\\n\")\n        detail_f.write(\"|-----------|------|------|------------|\\n\")\n        for _, row in suite_df.iterrows():\n            detail_f.write(\n                f\"| {row['name']} | {row['real_time']:.2f} | \"\n                f\"{row['time_unit']} | {row['iterations']} |\\n\"\n            )\n\n\ndef _write_suite_charts_markdown(f, suite: str, suite_parsed: \"pd.DataFrame\"):\n    \"\"\"Write chart markdown for a single suite to the report file.\"\"\"\n    # Check for registry entry first\n    if suite in _SUITE_CHART_REGISTRY:\n        for caption, chart_file in _SUITE_CHART_REGISTRY[suite]:\n            if suite == \"rw_lock\" and chart_file is None:\n                # Emit per-contention parallel charts\n                for cont in _RW_LOCK_CONTENTIONS:\n                    f.write(f\"**{cont} Iterations:**\\n\\n\")\n                    f.write(\n                        f\"![rw_lock parallel {cont}](rw_lock_parallel_{cont}_chart.png)\\n\\n\"\n                    )\n                continue\n            if caption:\n                f.write(f\"{caption}\\n\\n\")\n            alt = suite.replace(\"_\", \" \")\n            f.write(f\"![{alt}]({chart_file})\\n\\n\")\n        return\n\n    # Thread scaling suites with zoomed charts\n    if suite in _THREAD_SCALING_SUITES:\n        worksizes = suite_parsed[\"worksize\"].dropna().unique()\n        numeric_worksizes = [w for w in worksizes if str(w).isdigit()]\n        for worksize in sorted(numeric_worksizes, key=lambda x: int(x)):\n            ws_display = _format_worksize(worksize)\n            f.write(f\"**{ws_display} elements:**\\n\\n\")\n            f.write(f\"![{suite} {ws_display}]({suite}_{worksize}_chart.png)\\n\\n\")\n            f.write(f\"**{ws_display} elements (Y-Axis Zoomed):**\\n\\n\")\n            f.write(\n                f\"![{suite} {ws_display} zoomed]({suite}_{worksize}_zoomed_chart.png)\\n\\n\"\n            )\n        return\n\n    # Generic fallback: worksize line charts or single bar chart\n    has_thread_data = suite_parsed[\"threads\"].notna().any()\n    worksizes = suite_parsed[\"worksize\"].dropna().unique()\n\n    if has_thread_data and len(worksizes) > 0:\n        for worksize in sorted(\n            worksizes,\n            key=lambda x: (str(x).isdigit(), int(x) if str(x).isdigit() else 0),\n        ):\n            ws_display = _format_worksize(worksize)\n            chart_path = f\"{suite}_{worksize}_chart.png\"\n            f.write(f\"**{ws_display} elements:**\\n\\n\")\n            f.write(f\"![{suite} {ws_display}]({chart_path})\\n\\n\")\n            if suite == \"nested_pool\" and str(worksize) == \"1000000\":\n                f.write(\n                    \"*Note: folly::CPUThreadPoolExecutor is excluded from \"\n                    \"the 1M chart as it fails to complete (likely due to \"\n                    \"memory exhaustion from creating too many futures).*\\n\\n\"\n                )\n    else:\n        chart_path = f\"{suite}_chart.png\"\n        f.write(f\"![{suite} results]({chart_path})\\n\\n\")\n\n\ndef generate_markdown_report(\n    machine_info: Dict[str, Any],\n    results: List[Dict],\n    df: \"pd.DataFrame\",\n    output_dir: Path,\n):\n    \"\"\"Generate a markdown report of benchmark results.\"\"\"\n    report_path = output_dir / \"benchmark_report.md\"\n\n    with open(report_path, \"w\") as f:\n        f.write(\"# Dispenso Benchmark Results\\n\\n\")\n\n        # Machine info\n        f.write(\"## Machine Information\\n\\n\")\n        f.write(f\"- **Date**: {machine_info.get('timestamp', 'unknown')}\\n\")\n        f.write(\n            f\"- **Platform**: {machine_info.get('platform', 'unknown')} \"\n            f\"{machine_info.get('platform_release', '')}\\n\"\n        )\n        f.write(f\"- **CPU**: {machine_info.get('cpu_model', 'unknown')}\\n\")\n        f.write(f\"- **Hardware Threads**: {machine_info.get('cpu_cores', 'unknown')}\\n\")\n        f.write(f\"- **Memory**: {machine_info.get('memory_gb', 'unknown')} GB\\n\")\n        compiler = machine_info.get(\"compiler\", {})\n        if compiler:\n            f.write(f\"- **Compiler**: {compiler.get('compiler_summary', 'unknown')}\\n\")\n        f.write(\"\\n\")\n\n        # Results summary\n        f.write(\"## Results Summary\\n\\n\")\n\n        successful = sum(1 for r in results if r.get(\"success\"))\n        f.write(f\"- **Benchmarks run**: {len(results)}\\n\")\n        f.write(f\"- **Successful**: {successful}\\n\")\n        f.write(f\"- **Failed**: {len(results) - successful}\\n\\n\")\n\n        # Per-suite results with links to detailed tables\n        if not df.empty:\n            parsed = df[\"name\"].apply(parse_benchmark_name)\n            df_with_parsed = df.copy()\n            df_with_parsed[\"threads\"] = parsed.apply(lambda x: x[\"threads\"])\n            df_with_parsed[\"worksize\"] = parsed.apply(lambda x: x[\"worksize\"])\n\n            for suite in df[\"suite\"].unique():\n                f.write(f\"### {suite}\\n\\n\")\n\n                suite_df = df[df[\"suite\"] == suite].sort_values(\"real_time\")\n                suite_parsed = df_with_parsed[df_with_parsed[\"suite\"] == suite]\n\n                _write_suite_detail_table(suite, suite_df, output_dir)\n                _write_suite_charts_markdown(f, suite, suite_parsed)\n                f.write(f\"[View detailed results table]({suite}_details.md)\\n\\n\")\n\n        # Failures\n        failures = [r for r in results if not r.get(\"success\")]\n        if failures:\n            f.write(\"## Failures\\n\\n\")\n            for fail in failures:\n                f.write(f\"### {fail['name']}\\n\\n\")\n                f.write(f\"```\\n{fail.get('error', 'Unknown error')}\\n```\\n\\n\")\n\n    print(f\"Generated report: {report_path}\")\n\n\ndef main():\n    if not HAS_PLOTTING:\n        import sys\n\n        sys.exit(1)\n\n    parser = argparse.ArgumentParser(\n        description=\"Generate charts from dispenso benchmark results\"\n    )\n    parser.add_argument(\n        \"--input\",\n        \"-i\",\n        type=Path,\n        required=True,\n        help=\"Input JSON file from run_benchmarks.py\",\n    )\n    parser.add_argument(\n        \"--output-dir\",\n        \"-o\",\n        type=Path,\n        default=Path(\"charts\"),\n        help=\"Output directory for charts and reports\",\n    )\n    parser.add_argument(\n        \"--platform\",\n        \"-p\",\n        type=str,\n        default=None,\n        help=\"Platform identifier (e.g., 'linux-threadripper', 'macos-m2', 'windows-zen4'). \"\n        \"When set, output goes into a per-platform subdirectory under output-dir.\",\n    )\n\n    args = parser.parse_args()\n\n    # If platform specified, output into a subdirectory\n    output_dir = args.output_dir\n    if args.platform:\n        output_dir = output_dir / args.platform\n\n    # Load input data\n    print(f\"Loading results from: {args.input}\")\n    with open(args.input) as f:\n        data = json.load(f)\n\n    machine_info = data.get(\"machine_info\", {})\n    results = data.get(\"results\", [])\n\n    print(f\"  CPU: {machine_info.get('cpu_model', 'unknown')}\")\n    print(f\"  Hardware Threads: {machine_info.get('cpu_cores', 'unknown')}\")\n    compiler = machine_info.get(\"compiler\", {})\n    if compiler:\n        print(f\"  Compiler: {compiler.get('compiler_summary', 'unknown')}\")\n    if args.platform:\n        print(f\"  Platform: {args.platform}\")\n    print()\n\n    # Extract benchmark data\n    df = extract_benchmark_data(results)\n    if df.empty:\n        print(\"No benchmark data found in input file\")\n        import sys\n\n        sys.exit(1)\n\n    print(f\"Found {len(df)} benchmark results across {df['suite'].nunique()} suites\")\n    print()\n\n    # Generate charts\n    generate_charts(df, output_dir)\n    generate_markdown_report(machine_info, results, df, output_dir)\n\n    print(f\"\\nAll charts saved to: {output_dir}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/generate_plotly_benchmarks.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"Generate an interactive benchmark dashboard using Plotly.js.\n\nReads one or more dispenso benchmark JSON files and produces a single\nself-contained HTML file with interactive charts, dark/light theme,\nsidebar navigation, platform switching, and suite-specific visualizations.\n\nUsage:\n    python generate_plotly_benchmarks.py results/macos.json\n    python generate_plotly_benchmarks.py results/macos.json results/linux.json\n    python generate_plotly_benchmarks.py results/*.json -o docs/benchmarks/index.html\n\"\"\"\n\nimport argparse\nimport json\nimport re\nfrom collections import defaultdict\nfrom pathlib import Path\n\n\n# ─── Color palette (consistent with generate_charts.py) ────────────────────\n\nLIBRARY_COLORS = {\n    # Primary libraries - must be visually distinct from each other\n    \"dispenso\": \"#2ecc71\",  # Green\n    \"tbb\": \"#3498db\",  # Blue\n    \"omp\": \"#e74c3c\",  # Red\n    \"taskflow\": \"#f39c12\",  # Orange\n    \"folly\": \"#9b59b6\",  # Purple\n    \"serial\": \"#95a5a6\",  # Gray\n    \"std\": \"#1abc9c\",  # Teal\n    \"deque\": \"#e67e22\",  # Dark orange\n    \"async\": \"#f1c40f\",  # Yellow\n    # Dispenso variants - each distinct, avoiding primary library colors\n    # Must not use: blue (tbb), red (omp), orange (taskflow), purple (folly)\n    \"dispenso_static_chunk\": \"#1e8449\",  # Dark forest green\n    \"dispenso_auto_chunk\": \"#00bcd4\",  # Cyan (distinct from green family)\n    \"dispenso_static\": \"#1e8449\",  # Dark forest green\n    \"dispenso_auto\": \"#00bcd4\",  # Cyan (distinct from green family)\n    \"dispenso_bulk\": \"#1e8449\",  # Dark green, dashed in line charts\n    \"dispenso_par\": \"#27ae60\",  # Darker green (variant of dispenso)\n    \"dispenso_mostly_idle\": \"#48c9b0\",  # Teal-green\n    \"dispenso_very_idle\": \"#76d7c4\",  # Light teal\n    \"dispenso_mixed\": \"#58d68d\",  # Light green\n    \"dispenso2\": \"#27ae60\",  # Darker green\n    # Cascading parallel for variants\n    \"dispenso_blocking\": \"#2ecc71\",  # Green (same as dispenso)\n    \"dispenso_cascaded\": \"#2ecc71\",  # Green (distinguished by dash)\n    \"tbb_task_group\": \"#3498db\",  # Blue (distinguished by dash)\n    # for_each container variants - each distinct\n    \"for_each_n\": \"#2ecc71\",  # Green (dispenso default)\n    \"for_each_n_deque\": \"#e67e22\",  # Dark orange\n    \"for_each_n_list\": \"#3498db\",  # Blue\n    \"for_each_n_set\": \"#9b59b6\",  # Purple\n}\n\nIMPL_COLORS = {\n    \"serial\": \"#95a5a6\",\n    \"std::async\": \"#e74c3c\",\n    \"folly::Future\": \"#e67e22\",\n    \"dispenso::Future\": \"#3498db\",\n    \"dispenso::TaskSet\": \"#2ecc71\",\n    \"dispenso::TaskSet (bulk)\": \"#1e8449\",\n    \"dispenso::when_all\": \"#9b59b6\",\n    \"std::vector\": \"#808080\",\n    \"std::deque\": \"#FF8C00\",\n    \"tbb::concurrent_vector\": \"#4285F4\",\n    \"dispenso::ConcurrentVector\": \"#34A853\",\n    \"NopMutex\": \"#95a5a6\",\n    \"std::shared_mutex\": \"#e74c3c\",\n    \"dispenso::RWLock\": \"#2ecc71\",\n    \"std::function\": \"#e74c3c\",\n    \"dispenso::OnceFunction\": \"#2ecc71\",\n    \"InlineFunction\": \"#3498db\",\n    \"malloc/free\": \"#e74c3c\",\n    \"PoolAllocator\": \"#2ecc71\",\n    \"Arena\": \"#27ae60\",\n    \"NoLock\": \"#3498db\",\n    \"NoLock Arena\": \"#2980b9\",\n    \"SmallBufferAllocator\": \"#2ecc71\",\n    \"new/delete\": \"#e74c3c\",\n}\n\n\ndef get_color(name):\n    \"\"\"Get color for a library/implementation name.\n\n    Tries exact match first, then progressively longer prefix matches\n    to ensure dispenso_static gets a different color than dispenso.\n    \"\"\"\n    if name in IMPL_COLORS:\n        return IMPL_COLORS[name]\n    nl = name.lower()\n    # Try exact match in LIBRARY_COLORS\n    if nl in LIBRARY_COLORS:\n        return LIBRARY_COLORS[nl]\n    # Try longest-prefix match so 'dispenso_static' beats 'dispenso'\n    best_match = \"\"\n    best_color = \"#7f8c8d\"\n    for key, color in LIBRARY_COLORS.items():\n        if (nl.startswith(key) or key in nl) and len(key) > len(best_match):\n            best_match = key\n            best_color = color\n    return best_color\n\n\n# ─── Benchmark name parsing ────────────────────────────────────────────────\n\n\ndef parse_benchmark_name(name):\n    result = {\"library\": name, \"threads\": None, \"worksize\": None, \"raw\": name}\n    if \"<\" in name and \">\" in name:\n        m = re.match(r\"([^<]+)<([^>]+)>\", name)\n        if m:\n            result[\"library\"] = m.group(1)\n            result[\"worksize\"] = m.group(2)\n        return result\n    parts = name.split(\"/\")\n    if parts and parts[-1] == \"real_time\":\n        parts = parts[:-1]\n    if len(parts) >= 3:\n        result[\"library\"] = parts[0]\n        try:\n            result[\"threads\"] = int(parts[1])\n            result[\"worksize\"] = parts[2]\n        except (ValueError, IndexError):\n            pass\n    elif len(parts) == 2:\n        result[\"library\"] = parts[0]\n        try:\n            result[\"threads\"] = int(parts[1])\n            result[\"worksize\"] = \"default\"\n        except ValueError:\n            pass\n    return result\n\n\n# ─── Shared helpers ────────────────────────────────────────────────────────\n\n\ndef _format_worksize(ws):\n    \"\"\"Format a numeric worksize string into a compact label (e.g. '1000000' → '1M').\"\"\"\n    ws_int = int(ws) if ws.isdigit() else 0\n    if ws_int >= 1_000_000_000:\n        return f\"{ws_int // 1_000_000_000}B\"\n    if ws_int >= 1_000_000:\n        return f\"{ws_int // 1_000_000}M\"\n    if ws_int >= 1_000:\n        return f\"{ws_int // 1_000}K\"\n    return ws\n\n\ndef _lib_sort_key(lib):\n    \"\"\"Sort key: serial first, dispenso, then dispenso variants, then others.\"\"\"\n    ll = lib.lower()\n    if ll == \"serial\":\n        return (0, ll)\n    if ll == \"dispenso\":\n        return (1, ll)\n    if ll.startswith(\"dispenso\"):\n        return (2, ll)\n    return (3, ll)\n\n\n# ─── Suite-specific chart builders ──────────────────────────────────────────\n# Each returns a list of chart config dicts consumable by the JS renderer.\n\n\ndef _parse_line_benchmarks(benchmarks):\n    \"\"\"Parse benchmarks into grouped thread-scaling data and serial baselines.\"\"\"\n    size_map = {\n        \"kSmallSize\": \"1000\",\n        \"kMediumSize\": \"1000000\",\n        \"kLargeSize\": \"100000000\",\n        \"100\": \"100\",\n    }\n    grouped = defaultdict(dict)\n    serial_points = {}\n\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        name = bm[\"name\"].replace(\"BM_\", \"\")\n        parsed = parse_benchmark_name(name)\n        lib = parsed[\"library\"]\n\n        # Filter out auto_chunk, static_chunk, and other variants (auto, static)\n        # to keep charts clean - matches generate_charts.py behavior\n        lib_lower = lib.lower()\n        if \"auto\" in lib_lower or \"static\" in lib_lower:\n            continue\n\n        if parsed.get(\"worksize\") and \"<\" not in bm[\"name\"]:\n            # Slash-delimited: lib/threads/worksize\n            threads = parsed[\"threads\"]\n            if threads is not None:\n                grouped[parsed[\"worksize\"]][(lib, threads)] = bm[\"real_time\"]\n        elif \"<\" in bm[\"name\"]:\n            # Template: serial<kSmallSize>\n            m = re.match(r\"BM_([^<]+)<([^>]+)>\", bm[\"name\"])\n            if m:\n                ws_key = m.group(2)\n                serial_points[size_map.get(ws_key, ws_key)] = bm[\"real_time\"]\n\n    return grouped, serial_points\n\n\ndef build_line_charts(benchmarks, suite):\n    \"\"\"Thread-scaling line charts for simple_for, summing_for, trivial_compute, nested_for.\"\"\"\n    grouped, serial_points = _parse_line_benchmarks(benchmarks)\n\n    charts = []\n    for ws in sorted(grouped.keys(), key=lambda x: int(x) if x.isdigit() else 0):\n        by_lib = defaultdict(list)\n        thread_set = set()\n        for (lib, threads), time_ns in grouped[ws].items():\n            by_lib[lib].append((threads, time_ns))\n            thread_set.add(threads)\n\n        traces = []\n        # Add serial baseline first (acts as reference point)\n        if ws in serial_points:\n            max_t = max(thread_set) if thread_set else 1\n            traces.append(\n                {\n                    \"name\": \"serial\",\n                    \"x\": [1, max_t],\n                    \"y\": [serial_points[ws], serial_points[ws]],\n                    \"color\": get_color(\"serial\"),\n                    \"dash\": \"dash\",\n                    \"baseline\": True,\n                }\n            )\n\n        for lib in sorted(by_lib.keys(), key=_lib_sort_key):\n            points = sorted(by_lib[lib])\n            trace = {\n                \"name\": lib,\n                \"x\": [p[0] for p in points],\n                \"y\": [p[1] for p in points],\n                \"color\": get_color(lib),\n            }\n            # In cascading_parallel_for, distinguish blocking vs non-blocking with dashing.\n            # Blocking variants (tbb parallel_for, dispenso blocking) get dashed lines;\n            # non-blocking variants (tbb_task_group, dispenso cascaded) get solid lines.\n            if suite == \"cascading_parallel_for\":\n                ll = lib.lower()\n                if ll == \"tbb\" or \"blocking\" in ll:\n                    trace[\"dash\"] = \"dash\"\n            traces.append(trace)\n\n        label = _format_worksize(ws)\n        suite_display = suite.replace(\"_\", \" \").title()\n        if ws == \"default\":\n            title = suite_display\n        else:\n            title = f\"{suite_display} - {label} Elements\"\n        chart_cfg = {\n            \"id\": f\"{suite}_{ws}\",\n            \"suite\": suite,\n            \"type\": \"line\",\n            \"title\": title,\n            \"traces\": traces,\n            \"xaxis\": \"Threads\",\n            \"yaxis_unit\": \"ns\",\n        }\n        # simple_for has extreme outliers (taskflow ~7000x slower) where\n        # auto-zoom hides the comparison entirely.  Show full range so the\n        # user can see where taskflow sits, then zoom in interactively.\n        if suite == \"simple_for\":\n            chart_cfg[\"no_auto_zoom\"] = True\n        charts.append(chart_cfg)\n    return charts\n\n\n_CV_LIB_PREFIXES = [\"std_\", \"deque_\", \"tbb_\", \"dispenso_\"]\n_CV_LIB_MAP = {\n    \"std\": \"std::vector\",\n    \"deque\": \"std::deque\",\n    \"tbb\": \"tbb::concurrent_vector\",\n    \"dispenso\": \"dispenso::ConcurrentVector\",\n}\n_CV_LIB_ORDER = [\n    \"std::vector\",\n    \"std::deque\",\n    \"tbb::concurrent_vector\",\n    \"dispenso::ConcurrentVector\",\n]\n\n\ndef _parse_concurrent_vector_benchmarks(benchmarks):\n    \"\"\"Parse concurrent_vector benchmarks into (operation, library) -> time.\"\"\"\n    data = {}\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        for prefix in _CV_LIB_PREFIXES:\n            if clean.startswith(prefix):\n                lib_key = prefix.rstrip(\"_\")\n                op = clean[len(prefix) :]\n                lib = _CV_LIB_MAP.get(lib_key, lib_key)\n                data[(op, lib)] = bm[\"real_time\"]\n                break\n    return data\n\n\ndef _build_cv_group_chart(data, suite, group_name, ops_list, suffix, title_suffix):\n    \"\"\"Build a single concurrent vector chart for a serial or parallel group.\"\"\"\n    ops = [op for op in ops_list if any((op, lib) in data for lib in _CV_LIB_ORDER)]\n    libs = [lib for lib in _CV_LIB_ORDER if any((op, lib) in data for op in ops)]\n    if not ops or not libs:\n        return None\n\n    group_data = []\n    for lib in libs:\n        values = [data.get((op, lib), 0) for op in ops]\n        group_data.append({\"name\": lib, \"values\": values, \"color\": get_color(lib)})\n\n    label = \"Serial/Access\" if group_name == \"serial\" else \"Parallel\"\n    return {\n        \"id\": f\"concurrent_vector_{group_name}{suffix}\",\n        \"suite\": suite,\n        \"type\": \"grouped_bar_h\",\n        \"title\": f\"Concurrent Vector - {label} Operations{title_suffix}\",\n        \"categories\": [op.replace(\"_\", \" \") for op in ops],\n        \"groups\": group_data,\n        \"xaxis_unit\": \"ns\",\n        \"log_scale\": True,\n    }\n\n\ndef build_concurrent_vector_charts(benchmarks, suite):\n    \"\"\"Grouped horizontal bar charts split into serial/parallel operations.\"\"\"\n    serial_ops = [\n        \"push_back_serial\",\n        \"push_back_serial_reserve\",\n        \"iterate\",\n        \"iterate_reverse\",\n        \"lower_bound\",\n        \"index\",\n        \"random\",\n    ]\n    parallel_ops = [\n        \"parallel\",\n        \"parallel_reserve\",\n        \"parallel_clear\",\n        \"parallel_grow_by_10\",\n        \"parallel_grow_by_100\",\n        \"parallel_grow_by_max\",\n    ]\n\n    data = _parse_concurrent_vector_benchmarks(benchmarks)\n    suffix = \"_tcmalloc\" if \"tcmalloc\" in suite else \"\"\n    title_suffix = \" (tcmalloc)\" if suffix else \"\"\n\n    charts = []\n    for group_name, ops_list in [(\"serial\", serial_ops), (\"parallel\", parallel_ops)]:\n        chart = _build_cv_group_chart(\n            data, suite, group_name, ops_list, suffix, title_suffix\n        )\n        if chart:\n            charts.append(chart)\n    return charts\n\n\ndef _parse_future_benchmarks(benchmarks, impl_map, sizes):\n    \"\"\"Parse future benchmarks into data dict and error set.\"\"\"\n    data = {}\n    error_set = set()\n    for bm in benchmarks:\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        size = None\n        for sz in [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\"]:\n            if sz in clean:\n                size = sz.replace(\"k\", \"\").replace(\"Size\", \"\")\n                clean = clean.replace(f\"<{sz}>\", \"\")\n                break\n        impl = impl_map.get(clean, clean.replace(\"_\", \" \"))\n        if bm.get(\"error_occurred\"):\n            if size:\n                error_set.add((impl, size))\n            continue\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        if size:\n            data[(impl, size)] = bm[\"real_time\"]\n    return data, error_set\n\n\ndef _build_error_aware_groups(impls, available_sizes, data, error_set):\n    \"\"\"Build grouped bar data with error placeholders at max category height.\"\"\"\n    cat_maxes = {}\n    for s in available_sizes:\n        vals = [data.get((i, s), 0) for i in impls]\n        cat_maxes[s] = max(vals) if vals else 0\n\n    groups = []\n    for impl in impls:\n        values = []\n        error_indices = []\n        for idx, s in enumerate(available_sizes):\n            if (impl, s) in error_set:\n                values.append(cat_maxes[s])\n                error_indices.append(idx)\n            else:\n                values.append(data.get((impl, s), 0))\n        group = {\"name\": impl, \"values\": values, \"color\": get_color(impl)}\n        if error_indices:\n            group[\"error_indices\"] = error_indices\n        groups.append(group)\n    return groups\n\n\ndef build_future_charts(benchmarks, suite):\n    \"\"\"Grouped bar chart by tree size for future benchmark.\"\"\"\n    impl_map = {\n        \"serial_tree\": \"serial\",\n        \"std_tree\": \"std::async\",\n        \"folly_tree\": \"folly::Future\",\n        \"dispenso_tree\": \"dispenso::Future\",\n        \"dispenso_tree_when_all\": \"dispenso::when_all\",\n        \"dispenso_taskset_tree\": \"dispenso::TaskSet\",\n        \"dispenso_taskset_tree_bulk\": \"dispenso::TaskSet (bulk)\",\n    }\n    impl_order = [\n        \"serial\",\n        \"std::async\",\n        \"folly::Future\",\n        \"dispenso::Future\",\n        \"dispenso::TaskSet\",\n        \"dispenso::TaskSet (bulk)\",\n        \"dispenso::when_all\",\n    ]\n    sizes = [\"Small\", \"Medium\", \"Large\"]\n\n    data, error_set = _parse_future_benchmarks(benchmarks, impl_map, sizes)\n\n    impls = [\n        i\n        for i in impl_order\n        if any((i, s) in data or (i, s) in error_set for s in sizes)\n    ]\n    available_sizes = [\n        s for s in sizes if any((i, s) in data or (i, s) in error_set for i in impls)\n    ]\n\n    groups = _build_error_aware_groups(impls, available_sizes, data, error_set)\n\n    return [\n        {\n            \"id\": \"future\",\n            \"suite\": suite,\n            \"type\": \"grouped_bar_v\",\n            \"title\": \"Future/Async Tree Build Benchmark\",\n            \"categories\": available_sizes,\n            \"groups\": groups,\n            \"yaxis_unit\": \"ns\",\n            \"xaxis\": \"Tree Size\",\n        }\n    ]\n\n\ndef build_graph_charts(benchmarks, suite):\n    \"\"\"Horizontal bar chart with logical grouping for graph/graph_scene.\"\"\"\n    # graph_scene: dispenso apples-to-apples with taskflow first,\n    # then partial_revaluation last (unique dispenso feature)\n    graph_scene_order = [\n        \"scene graph parallel for\",\n        \"scene graph taskflow\",\n        \"scene graph concurrent task set\",\n        \"scene graph partial revaluation\",\n    ]\n    graph_order = [\n        \"taskflow build big tree\",\n        \"build big tree (Graph)\",\n        \"build big tree (BiProp)\",\n        \"build bi prop dependency chain\",\n        \"build bi prop dependency group\",\n        \"build dependency chain (Graph)\",\n        \"build dependency chain (BiProp)\",\n        \"execute dependency chain (Graph)\",\n        \"execute dependency chain (BiProp)\",\n        \"forward propagator node (Graph)\",\n        \"forward propagator node (BiProp)\",\n    ]\n    group_order = graph_scene_order if suite == \"graph_scene\" else graph_order\n\n    items = []\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        clean = clean.replace(\"<dispenso::BiPropGraph>\", \" (BiProp)\")\n        clean = clean.replace(\"<dispenso::Graph>\", \" (Graph)\")\n        clean = clean.replace(\"_\", \" \")\n        items.append({\"name\": clean, \"time_ns\": bm[\"real_time\"]})\n\n    # Sort by group_order, then alphabetical for unknowns\n    def sort_key(item):\n        try:\n            return (group_order.index(item[\"name\"]), \"\")\n        except ValueError:\n            return (len(group_order), item[\"name\"])\n\n    items.sort(key=sort_key)\n\n    def color_for(name):\n        if \"taskflow\" in name.lower():\n            return \"#f39c12\"\n        if \"BiProp\" in name:\n            return \"#27ae60\"\n        return \"#2ecc71\"\n\n    suite_display = suite.replace(\"_\", \" \").title()\n    return [\n        {\n            \"id\": f\"{suite}_bar\",\n            \"suite\": suite,\n            \"type\": \"bar_h_colored\",\n            \"title\": f\"{suite_display} Benchmark\",\n            \"items\": [\n                {\n                    \"name\": i[\"name\"],\n                    \"time_ns\": i[\"time_ns\"],\n                    \"color\": color_for(i[\"name\"]),\n                }\n                for i in items\n            ],\n            \"xaxis_unit\": \"ns\",\n        }\n    ]\n\n\ndef _parse_rw_lock_benchmarks(benchmarks):\n    \"\"\"Parse rw_lock benchmarks into (operation, mutex, threads, contention) → time.\"\"\"\n    data = {}\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        mutex = None\n        for m in [\"NopMutex\", \"std::shared_mutex\", \"dispenso::RWLock\"]:\n            if m in clean:\n                mutex = m\n                clean = clean.replace(f\"<{m}>\", \"\")\n                break\n        parts = clean.split(\"/\")\n        operation = parts[0]\n        if operation == \"serial\":\n            cont = parts[1] if len(parts) > 1 else None\n            data[(operation, mutex, None, cont)] = bm[\"real_time\"]\n        else:\n            threads = parts[1] if len(parts) > 1 else None\n            cont = parts[2] if len(parts) > 2 else None\n            data[(operation, mutex, threads, cont)] = bm[\"real_time\"]\n    return data\n\n\ndef _build_grouped_bar_chart(chart_id, suite, title, categories, mutexes, data, key_fn):\n    \"\"\"Build a grouped horizontal bar chart config for a set of mutexes.\"\"\"\n    groups = []\n    for mutex in mutexes:\n        values = [data.get(key_fn(mutex, cat), 0) for cat in categories]\n        if any(v > 0 for v in values):\n            groups.append({\"name\": mutex, \"values\": values, \"color\": get_color(mutex)})\n    if not groups:\n        return None\n    return {\n        \"id\": chart_id,\n        \"suite\": suite,\n        \"type\": \"grouped_bar_h\",\n        \"title\": title,\n        \"categories\": [str(c) for c in categories],\n        \"groups\": groups,\n        \"xaxis_unit\": \"ns\",\n    }\n\n\ndef _build_rw_lock_parallel_charts(data, suite, mutexes):\n    \"\"\"Build per-contention parallel RW lock charts.\"\"\"\n    parallel_keys = [k for k in data if k[0] == \"parallel\"]\n    parallel_conts = sorted(set(k[3] for k in parallel_keys if k[3]), key=int)\n    parallel_threads = sorted(set(k[2] for k in parallel_keys if k[2]), key=int)\n    charts = []\n    for cont in parallel_conts:\n        chart = _build_grouped_bar_chart(\n            f\"rw_lock_parallel_{cont}\",\n            suite,\n            f\"RW Lock - Parallel ({cont} iterations)\",\n            parallel_threads,\n            mutexes,\n            data,\n            lambda mutex, t, c=cont: (\"parallel\", mutex, t, c),\n        )\n        if chart:\n            chart[\"categories\"] = [f\"{t} threads\" for t in parallel_threads]\n            charts.append(chart)\n    return charts\n\n\ndef build_rw_lock_charts(benchmarks, suite):\n    \"\"\"Serial + per-contention parallel grouped bar charts.\"\"\"\n    data = _parse_rw_lock_benchmarks(benchmarks)\n\n    mutexes_serial = [\"NopMutex\", \"std::shared_mutex\", \"dispenso::RWLock\"]\n    mutexes_parallel = [\"std::shared_mutex\", \"dispenso::RWLock\"]\n    charts = []\n\n    # Serial chart\n    serial_conts = sorted(set(k[3] for k in data if k[0] == \"serial\" and k[3]), key=int)\n    if serial_conts:\n        chart = _build_grouped_bar_chart(\n            \"rw_lock_serial\",\n            suite,\n            \"RW Lock - Serial Operations\",\n            serial_conts,\n            mutexes_serial,\n            data,\n            lambda mutex, c: (\"serial\", mutex, None, c),\n        )\n        if chart:\n            chart[\"categories\"] = [f\"{c} iterations\" for c in serial_conts]\n            charts.append(chart)\n\n    charts.extend(_build_rw_lock_parallel_charts(data, suite, mutexes_parallel))\n    return charts\n\n\n_OF_SIZE_ORDER = [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\", \"kExtraLargeSize\"]\n_OF_SIZE_LABELS = {\n    \"kSmallSize\": \"Small\",\n    \"kMediumSize\": \"Medium\",\n    \"kLargeSize\": \"Large\",\n    \"kExtraLargeSize\": \"Extra Large\",\n}\n_OF_FUNC_COLORS = {\n    \"Std Function\": \"#e74c3c\",\n    \"Once Function\": \"#2ecc71\",\n    \"Inline Function\": \"#3498db\",\n}\n\n\ndef _parse_once_function_benchmarks(benchmarks):\n    \"\"\"Parse once_function benchmarks into (op, func_type, size) -> time.\"\"\"\n    data = {}\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        if clean.startswith(\"move_\"):\n            op = \"move\"\n            clean = clean[5:]\n        elif clean.startswith(\"queue_\"):\n            op = \"queue\"\n            clean = clean[6:]\n        else:\n            continue\n        if \"<\" not in clean:\n            continue\n        func_type, size = clean.split(\"<\")\n        size = size.rstrip(\">\")\n        func_type = func_type.replace(\"_\", \" \").title()\n        data[(op, func_type, size)] = bm[\"real_time\"]\n    return data\n\n\ndef build_once_function_charts(benchmarks, suite):\n    \"\"\"Move vs queue operations, grouped by size.\"\"\"\n    data = _parse_once_function_benchmarks(benchmarks)\n\n    charts = []\n    for op in [\"move\", \"queue\"]:\n        func_types = sorted(set(k[1] for k in data if k[0] == op))\n        sizes = [\n            s for s in _OF_SIZE_ORDER if any((op, ft, s) in data for ft in func_types)\n        ]\n        if not sizes or not func_types:\n            continue\n        groups = []\n        for ft in func_types:\n            values = [data.get((op, ft, s), 0) for s in sizes]\n            groups.append(\n                {\n                    \"name\": ft,\n                    \"values\": values,\n                    \"color\": _OF_FUNC_COLORS.get(ft, \"#9b59b6\"),\n                }\n            )\n        charts.append(\n            {\n                \"id\": f\"once_function_{op}\",\n                \"suite\": suite,\n                \"type\": \"grouped_bar_h\",\n                \"title\": f\"Once Function - {op.title()} Operations\",\n                \"categories\": [_OF_SIZE_LABELS.get(s, s) for s in sizes],\n                \"groups\": groups,\n                \"xaxis_unit\": \"ns\",\n            }\n        )\n    return charts\n\n\n_ALLOC_PREFIXES = [\n    (\"mallocfree_threaded\", \"malloc/free\", 19),\n    (\"mallocfree\", \"malloc/free\", 10),\n    (\"nl_pool_allocator_arena\", \"NoLock Arena\", 23),\n    (\"nl_pool_allocator\", \"NoLock\", 17),\n    (\"pool_allocator_arena\", \"Arena\", 20),\n    (\"pool_allocator_threaded\", \"PoolAllocator\", 23),\n    (\"pool_allocator\", \"PoolAllocator\", 14),\n]\n\n\ndef _parse_pool_allocator_benchmarks(benchmarks):\n    \"\"\"Parse pool allocator benchmarks into (alloc_type, size, threads, iters) → time.\"\"\"\n    data = {}\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        at = None\n        rest = \"\"\n        for prefix, alloc_type, prefix_len in _ALLOC_PREFIXES:\n            if clean.startswith(prefix):\n                at = alloc_type\n                rest = clean[prefix_len:]\n                break\n        if at is None:\n            continue\n\n        size = \"unknown\"\n        threads = 1\n        iters = 0\n        if \"<\" in rest:\n            params, iters_str = rest.split(\">\")\n            params = params.lstrip(\"<\")\n            if \",\" in params:\n                size, threads = params.split(\",\")\n                threads = int(threads)\n            else:\n                size = params\n            if \"/\" in iters_str:\n                iters = int(iters_str.lstrip(\"/\"))\n        elif \"/\" in rest:\n            iters = int(rest.lstrip(\"/\"))\n        data[(at, size, threads, iters)] = bm[\"real_time\"]\n    return data\n\n\n_PA_SIZE_ORDER = [\"kSmallSize\", \"kMediumSize\", \"kLargeSize\"]\n_PA_SIZE_LABELS = {\"kSmallSize\": \"S\", \"kMediumSize\": \"M\", \"kLargeSize\": \"L\"}\n_PA_ALLOC_SINGLE = [\"malloc/free\", \"PoolAllocator\", \"Arena\", \"NoLock\", \"NoLock Arena\"]\n_PA_ALLOC_MULTI = [\"malloc/free\", \"PoolAllocator\"]\n\n\ndef _build_pool_allocator_chart(data, suite, tc):\n    \"\"\"Build a single pool allocator chart for a given thread count.\"\"\"\n    if tc == 1:\n        alloc_types = _PA_ALLOC_SINGLE\n        title_suffix = \"Single-threaded\"\n    else:\n        alloc_types = _PA_ALLOC_MULTI\n        title_suffix = f\"{tc} Threads\"\n\n    alloc_types = [\n        a for a in alloc_types if any(k[0] == a and k[2] == tc for k in data)\n    ]\n    iters_list = sorted(set(k[3] for k in data if k[2] == tc))\n\n    categories = []\n    for size in _PA_SIZE_ORDER:\n        for it in iters_list:\n            il = f\"{it // 1000}K\" if it >= 1000 else str(it)\n            categories.append(f\"{_PA_SIZE_LABELS.get(size, size)}/{il}\")\n\n    groups = []\n    for at in alloc_types:\n        values = [\n            data.get((at, size, tc, it), 0)\n            for size in _PA_SIZE_ORDER\n            for it in iters_list\n        ]\n        groups.append({\"name\": at, \"values\": values, \"color\": get_color(at)})\n\n    if not groups:\n        return None\n    return {\n        \"id\": f\"pool_allocator_{tc}t\",\n        \"suite\": suite,\n        \"type\": \"grouped_bar_h\",\n        \"title\": f\"Pool Allocator - {title_suffix}\",\n        \"categories\": categories,\n        \"groups\": groups,\n        \"xaxis_unit\": \"ns\",\n        \"log_scale\": True,\n    }\n\n\ndef build_pool_allocator_charts(benchmarks, suite):\n    \"\"\"Per-thread-count grouped bar charts.\"\"\"\n    data = _parse_pool_allocator_benchmarks(benchmarks)\n    thread_counts = sorted(set(k[2] for k in data))\n    charts = []\n    for tc in thread_counts:\n        chart = _build_pool_allocator_chart(data, suite, tc)\n        if chart:\n            charts.append(chart)\n    return charts\n\n\ndef build_small_buffer_charts(benchmarks, suite):\n    \"\"\"Horizontal bars, grouped side-by-side by allocator type.\"\"\"\n    items = []\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        clean = (\n            clean.replace(\"<kSmallSize>\", \"[S]\")\n            .replace(\"<kMediumSize>\", \"[M]\")\n            .replace(\"<kLargeSize>\", \"[L]\")\n        )\n        clean = (\n            clean.replace(\"<kSmallSize,\", \"[S,\")\n            .replace(\"<kMediumSize,\", \"[M,\")\n            .replace(\"<kLargeSize,\", \"[L,\")\n        )\n        clean = clean.replace(\">\", \"]\").replace(\"_\", \" \")\n        is_sb = \"small buffer\" in clean.lower()\n        items.append(\n            {\n                \"name\": clean,\n                \"time_ns\": bm[\"real_time\"],\n                \"color\": \"#2ecc71\" if is_sb else \"#e74c3c\",\n            }\n        )\n\n    # Sort by size, iterations, threads, allocator type (to interleave)\n    def sort_key(item):\n        n = item[\"name\"]\n        s = 0 if \"[S]\" in n or \"[S,\" in n else (1 if \"[M]\" in n or \"[M,\" in n else 2)\n        it_m = re.search(r\"/(\\d+)\", n)\n        it = int(it_m.group(1)) if it_m else 0\n        th_m = re.search(r\"threads:(\\d+)\", n)\n        th = int(th_m.group(1)) if th_m else 1\n        is_sb = 1 if \"small buffer\" in n.lower() else 0\n        return (s, it, th, is_sb)\n\n    items.sort(key=sort_key)\n\n    return [\n        {\n            \"id\": \"small_buffer\",\n            \"suite\": suite,\n            \"type\": \"bar_h_colored\",\n            \"title\": \"Small Buffer Allocator Benchmark\",\n            \"items\": items,\n            \"xaxis_unit\": \"ns\",\n            \"legend\": [\n                {\"name\": \"SmallBufferAllocator\", \"color\": \"#2ecc71\"},\n                {\"name\": \"new/delete\", \"color\": \"#e74c3c\"},\n            ],\n        }\n    ]\n\n\ndef _parse_timed_task_benchmark(bm):\n    \"\"\"Parse a single timed_task benchmark entry into a row dict, or None.\"\"\"\n    mean_err = bm.get(\"mean\")\n    stddev_err = bm.get(\"stddev\")\n    if mean_err is None or stddev_err is None:\n        return None\n    m = re.match(r\"BM_(\\w+)<(.+)>\", bm[\"name\"])\n    if not m:\n        return None\n    func_name = m.group(1)\n    template_args = m.group(2).strip()\n\n    if \"mixed\" in func_name:\n        library = func_name.replace(\"_mixed\", \"\")\n        steady = template_args.strip().lower() == \"true\"\n        config_label = f\"Mixed ({'Steady' if steady else 'Normal'})\"\n    else:\n        library = func_name\n        parts = [p.strip() for p in template_args.split(\",\")]\n        if len(parts) != 2:\n            return None\n        try:\n            period_ms = int(parts[0])\n        except ValueError:\n            return None\n        steady = parts[1].lower() == \"true\"\n        config_label = f\"{period_ms}ms ({'Steady' if steady else 'Normal'})\"\n\n    return {\n        \"library\": library,\n        \"config\": config_label,\n        \"mean_us\": mean_err * 1e6,\n        \"stddev_us\": stddev_err * 1e6,\n    }\n\n\ndef build_timed_task_charts(benchmarks, suite):\n    \"\"\"Scheduling jitter bar chart with error bars.\"\"\"\n    rows = []\n    for bm in benchmarks:\n        row = _parse_timed_task_benchmark(bm)\n        if row:\n            rows.append(row)\n\n    if not rows:\n        return []\n\n    # Order configs\n    configs = []\n    seen = set()\n    for r in sorted(rows, key=lambda r: (r[\"config\"].startswith(\"Mixed\"), r[\"config\"])):\n        if r[\"config\"] not in seen:\n            configs.append(r[\"config\"])\n            seen.add(r[\"config\"])\n\n    libraries = sorted(set(r[\"library\"] for r in rows))\n    groups = []\n    for lib in libraries:\n        values = []\n        errors = []\n        for cfg in configs:\n            match = [r for r in rows if r[\"library\"] == lib and r[\"config\"] == cfg]\n            if match:\n                values.append(match[0][\"mean_us\"])\n                errors.append(match[0][\"stddev_us\"])\n            else:\n                values.append(0)\n                errors.append(0)\n        groups.append(\n            {\n                \"name\": lib,\n                \"values\": values,\n                \"errors\": errors,\n                \"color\": get_color(lib),\n            }\n        )\n\n    return [\n        {\n            \"id\": \"timed_task\",\n            \"suite\": suite,\n            \"type\": \"grouped_bar_h_error\",\n            \"title\": \"Timed Task - Scheduling Jitter\",\n            \"categories\": configs,\n            \"groups\": groups,\n            \"xaxis_label\": \"Mean Scheduling Error (us)\",\n        }\n    ]\n\n\ndef build_pipeline_charts(benchmarks, suite):\n    \"\"\"Bar chart for pipeline benchmark, grouped by serial vs parallel.\"\"\"\n    items = []\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        clean = clean.replace(\"_\", \" \")\n        color = get_color(clean.split()[0] if clean.split() else \"\")\n        items.append({\"name\": clean, \"time_ns\": bm[\"real_time\"], \"color\": color})\n\n    # Sort: serial first, then by library within each group\n    def sort_key(item):\n        n = item[\"name\"].lower()\n        is_par = \"par\" in n or \"parallel\" in n\n        lib_order = 0\n        if \"serial\" in n:\n            lib_order = 0\n        elif \"dispenso\" in n:\n            lib_order = 1\n        elif \"tbb\" in n:\n            lib_order = 2\n        elif \"taskflow\" in n:\n            lib_order = 3\n        else:\n            lib_order = 4\n        return (1 if is_par else 0, lib_order, n)\n\n    items.sort(key=sort_key)\n\n    suite_display = suite.replace(\"_\", \" \").title()\n    return [\n        {\n            \"id\": f\"{suite}_bar\",\n            \"suite\": suite,\n            \"type\": \"bar_h_colored\",\n            \"title\": f\"{suite_display} Benchmark\",\n            \"items\": items,\n            \"xaxis_unit\": \"ns\",\n        }\n    ]\n\n\ndef _parse_generic_line_benchmarks(benchmarks):\n    \"\"\"Parse benchmarks into thread-scaling data and error tracking.\n\n    Returns (grouped, errored) where:\n    - grouped: {worksize: {(lib, threads): real_time}}\n    - errored: {worksize: set of libs with error_occurred}\n    \"\"\"\n    grouped = defaultdict(dict)\n    errored = defaultdict(set)\n\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        parsed = parse_benchmark_name(bm[\"name\"].replace(\"BM_\", \"\"))\n        lib = parsed[\"library\"]\n        threads = parsed.get(\"threads\")\n        ws = parsed.get(\"worksize\")\n        if threads is not None and ws is not None:\n            if bm.get(\"error_occurred\"):\n                errored[ws].add(lib)\n                continue\n            grouped[ws][(lib, threads)] = bm[\"real_time\"]\n\n    return grouped, errored\n\n\ndef _skipped_libs_list(errored_libs, valid_libs):\n    \"\"\"Build skipped_libs chart config for libraries that only have errors.\"\"\"\n    skipped = [lib for lib in sorted(errored_libs) if lib not in valid_libs]\n    if not skipped:\n        return None\n    return [{\"name\": lib, \"color\": get_color(lib)} for lib in skipped]\n\n\ndef build_generic_line_charts(benchmarks, suite):\n    \"\"\"Generic line charts for suites with thread/worksize structure.\"\"\"\n    grouped, errored = _parse_generic_line_benchmarks(benchmarks)\n\n    charts = []\n    for ws in sorted(grouped.keys(), key=lambda x: int(x) if x.isdigit() else 0):\n        by_lib = defaultdict(list)\n        for (lib, threads), t in grouped[ws].items():\n            by_lib[lib].append((threads, t))\n\n        traces = []\n        for lib in sorted(by_lib.keys(), key=_lib_sort_key):\n            points = sorted(by_lib[lib])\n            trace = {\n                \"name\": lib,\n                \"x\": [p[0] for p in points],\n                \"y\": [p[1] for p in points],\n                \"color\": get_color(lib),\n            }\n            if \"bulk\" in lib.lower():\n                trace[\"dash\"] = \"dash\"\n            traces.append(trace)\n\n        label = _format_worksize(ws)\n        suite_display = suite.replace(\"_\", \" \").title()\n        chart_cfg = {\n            \"id\": f\"{suite}_{ws}\",\n            \"suite\": suite,\n            \"type\": \"line\",\n            \"title\": suite_display\n            if ws == \"default\"\n            else f\"{suite_display} - {label} Elements\",\n            \"traces\": traces,\n            \"xaxis\": \"Threads\",\n            \"yaxis_unit\": \"ns\",\n        }\n        skipped = _skipped_libs_list(errored.get(ws, set()), by_lib)\n        if skipped:\n            chart_cfg[\"skipped_libs\"] = skipped\n        charts.append(chart_cfg)\n\n    # Also generate charts for worksizes where ALL libraries errored\n    # (no entries in grouped but present in errored)\n    for ws in sorted(errored.keys(), key=lambda x: int(x) if x.isdigit() else 0):\n        if ws in grouped:\n            continue\n        label = _format_worksize(ws)\n        suite_display = suite.replace(\"_\", \" \").title()\n        charts.append(\n            {\n                \"id\": f\"{suite}_{ws}\",\n                \"suite\": suite,\n                \"type\": \"line\",\n                \"title\": f\"{suite_display} - {label} Elements\",\n                \"traces\": [],\n                \"xaxis\": \"Threads\",\n                \"yaxis_unit\": \"ns\",\n                \"skipped_libs\": [\n                    {\"name\": lib, \"color\": get_color(lib)}\n                    for lib in sorted(errored[ws])\n                ],\n            }\n        )\n    return charts\n\n\ndef build_generic_bar_charts(benchmarks, suite):\n    \"\"\"Generic bar chart, items grouped so alternatives for same case are side-by-side.\"\"\"\n    items = []\n    for bm in benchmarks:\n        if bm.get(\"run_type\") != \"iteration\":\n            continue\n        clean = bm[\"name\"].replace(\"BM_\", \"\").replace(\"/real_time\", \"\")\n        clean_display = clean.replace(\"_\", \" \")\n        items.append(\n            {\n                \"name\": clean_display,\n                \"time_ns\": bm[\"real_time\"],\n                \"color\": get_color(clean_display),\n            }\n        )\n\n    # Sort: serial first, then group by operation\n    def sort_key(item):\n        n = item[\"name\"].lower()\n        is_par = \"par\" in n or \"parallel\" in n\n        lib_order = 0\n        if \"serial\" in n:\n            lib_order = 0\n        elif \"dispenso\" in n:\n            lib_order = 1\n        elif \"tbb\" in n:\n            lib_order = 2\n        elif \"taskflow\" in n:\n            lib_order = 3\n        elif \"omp\" in n:\n            lib_order = 4\n        elif \"folly\" in n:\n            lib_order = 5\n        elif \"std\" in n:\n            lib_order = 6\n        else:\n            lib_order = 7\n        return (1 if is_par else 0, lib_order, n)\n\n    items.sort(key=sort_key)\n\n    suite_display = suite.replace(\"_\", \" \").title()\n    return [\n        {\n            \"id\": f\"{suite}_bar\",\n            \"suite\": suite,\n            \"type\": \"bar_h_colored\",\n            \"title\": f\"{suite_display} Benchmark\",\n            \"items\": items,\n            \"xaxis_unit\": \"ns\",\n        }\n    ]\n\n\n# ─── Chart dispatch ─────────────────────────────────────────────────────────\n\nSPECIALIZED_LINE = {\n    \"simple_for\",\n    \"summing_for\",\n    \"trivial_compute\",\n    \"nested_for\",\n    \"cascading_parallel_for\",\n}\n\n\ndef build_charts_for_suite(benchmarks, suite):\n    \"\"\"Route suite to appropriate chart builder.\"\"\"\n    if suite in SPECIALIZED_LINE:\n        return build_line_charts(benchmarks, suite)\n    if suite in (\"concurrent_vector\", \"concurrent_vector_tcmalloc\"):\n        return build_concurrent_vector_charts(benchmarks, suite)\n    if suite == \"future\":\n        return build_future_charts(benchmarks, suite)\n    if suite in (\"graph\", \"graph_scene\"):\n        return build_graph_charts(benchmarks, suite)\n    if suite == \"rw_lock\":\n        return build_rw_lock_charts(benchmarks, suite)\n    if suite == \"once_function\":\n        return build_once_function_charts(benchmarks, suite)\n    if suite == \"pool_allocator\":\n        return build_pool_allocator_charts(benchmarks, suite)\n    if suite == \"small_buffer\":\n        return build_small_buffer_charts(benchmarks, suite)\n    if suite == \"timed_task\":\n        return build_timed_task_charts(benchmarks, suite)\n    if suite == \"pipeline\":\n        return build_pipeline_charts(benchmarks, suite)\n    # Generic fallback: check if data has thread structure\n    has_threads = any(\n        parse_benchmark_name(bm[\"name\"].replace(\"BM_\", \"\")).get(\"threads\") is not None\n        for bm in benchmarks\n        if bm.get(\"run_type\") == \"iteration\"\n    )\n    if has_threads:\n        return build_generic_line_charts(benchmarks, suite)\n    return build_generic_bar_charts(benchmarks, suite)\n\n\n# ─── HTML generation ────────────────────────────────────────────────────────\n\n\ndef generate_html(platform_data, output_path):\n    \"\"\"Generate the full interactive HTML page.\n\n    platform_data: list of {\"id\": str, \"label\": str, \"machine\": dict, \"charts\": list}\n    \"\"\"\n    # Build per-platform JSON blob\n    platforms_json = json.dumps(platform_data)\n\n    # Collect all suites across platforms for navigation\n    all_suites = []\n    seen = set()\n    for pd_item in platform_data:\n        for chart in pd_item[\"charts\"]:\n            s = chart[\"suite\"]\n            if s not in seen:\n                all_suites.append(s)\n                seen.add(s)\n\n    nav_items = \"\\n\".join(\n        f'<a href=\"#section-{s}\" class=\"nav-link\" data-suite=\"{s}\">'\n        f\"{s.replace('_', ' ').title()}</a>\"\n        for s in all_suites\n    )\n\n    html = f\"\"\"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Dispenso Benchmark Results</title>\n<script src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>\n<style>\n:root {{\n  --bg-primary: #0d1117; --bg-secondary: #161b22; --bg-tertiary: #21262d;\n  --bg-card: #1c2128; --text-primary: #e6edf3; --text-secondary: #8b949e;\n  --text-muted: #6e7681; --border: #30363d; --accent: #2ecc71;\n  --accent-hover: #27ae60; --accent-dim: rgba(46,204,113,0.15);\n  --shadow: rgba(0,0,0,0.3); --nav-width: 240px; --header-height: 56px;\n}}\nhtml[data-theme=\"light\"] {{\n  --bg-primary: #ffffff; --bg-secondary: #f6f8fa; --bg-tertiary: #eaeef2;\n  --bg-card: #ffffff; --text-primary: #1f2328; --text-secondary: #656d76;\n  --text-muted: #8b949e; --border: #d0d7de; --accent: #1a7f37;\n  --accent-hover: #116329; --accent-dim: rgba(26,127,55,0.1);\n  --shadow: rgba(31,35,40,0.12);\n}}\n* {{ margin:0; padding:0; box-sizing:border-box; }}\nbody {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; background: var(--bg-primary); color: var(--text-primary); line-height: 1.5; }}\n.header {{ position:fixed; top:0; left:0; right:0; height:var(--header-height); background:var(--bg-secondary); border-bottom:1px solid var(--border); display:flex; align-items:center; padding:0 20px; z-index:100; }}\n.header-logo {{ display:flex; align-items:center; gap:10px; font-size:18px; font-weight:600; }}\n.header-logo .icon {{ width:28px; height:28px; background:var(--accent); border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:15px; color:#fff; font-weight:700; }}\n.header-right {{ margin-left:auto; display:flex; align-items:center; gap:12px; }}\n.btn {{ background:var(--bg-tertiary); border:1px solid var(--border); color:var(--text-secondary); padding:5px 12px; border-radius:6px; cursor:pointer; font-size:13px; transition:all .2s; }}\n.btn:hover {{ color:var(--text-primary); border-color:var(--accent); }}\n.btn.active {{ background:var(--accent-dim); border-color:var(--accent); color:var(--accent); font-weight:500; }}\n.platform-select {{ background:var(--bg-tertiary); border:1px solid var(--border); color:var(--text-primary); padding:5px 12px; border-radius:6px; font-size:13px; cursor:pointer; }}\n.platform-select option {{ background:var(--bg-secondary); color:var(--text-primary); }}\n.sidebar {{ position:fixed; top:var(--header-height); left:0; bottom:0; width:var(--nav-width); background:var(--bg-secondary); border-right:1px solid var(--border); overflow-y:auto; padding:12px 0; z-index:50; scrollbar-width:thin; scrollbar-color:var(--border) transparent; }}\n.search-box {{ margin:0 14px 12px; }}\n.search-input {{ width:100%; padding:6px 10px; background:var(--bg-tertiary); border:1px solid var(--border); border-radius:6px; color:var(--text-primary); font-size:12px; outline:none; }}\n.search-input:focus {{ border-color:var(--accent); }}\n.search-input::placeholder {{ color:var(--text-muted); }}\n.nav-section-title {{ padding:6px 14px; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:.5px; color:var(--text-muted); }}\n.nav-link {{ display:block; padding:5px 14px; color:var(--text-secondary); text-decoration:none; font-size:13px; transition:all .15s; border-left:3px solid transparent; }}\n.nav-link:hover {{ color:var(--text-primary); background:var(--bg-tertiary); }}\n.nav-link.active {{ color:var(--accent); background:var(--accent-dim); border-left-color:var(--accent); font-weight:500; }}\n.main {{ margin-left:var(--nav-width); margin-top:var(--header-height); padding:24px; max-width:1400px; }}\n.info-cards {{ display:grid; grid-template-columns:repeat(auto-fit, minmax(220px,1fr)); gap:12px; margin-bottom:24px; }}\n.info-card {{ background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:14px; transition:border-color .2s; }}\n.info-card:hover {{ border-color:var(--accent); }}\n.info-card .label {{ font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:.5px; color:var(--text-muted); margin-bottom:4px; }}\n.info-card .value {{ font-size:16px; font-weight:600; }}\n.info-card .detail {{ font-size:12px; color:var(--text-secondary); margin-top:2px; }}\n.stats-bar {{ display:flex; gap:20px; margin-bottom:24px; padding:12px 16px; background:var(--bg-card); border:1px solid var(--border); border-radius:10px; font-size:13px; }}\n.stat-item {{ display:flex; align-items:center; gap:6px; }}\n.stat-dot {{ width:7px; height:7px; border-radius:50%; }}\n.stat-dot.ok {{ background:#2ecc71; }} .stat-dot.info {{ background:#3498db; }}\n.benchmark-section {{ margin-bottom:40px; scroll-margin-top:calc(var(--header-height) + 20px); }}\n.section-title {{ font-size:20px; font-weight:600; margin-bottom:16px; padding-bottom:8px; border-bottom:1px solid var(--border); }}\n.chart-container {{ background:var(--bg-card); border:1px solid var(--border); border-radius:10px; padding:12px; margin-bottom:12px; transition:border-color .2s; }}\n.chart-container:hover {{ border-color:var(--accent); box-shadow:0 2px 8px var(--shadow); }}\n.chart {{ width:100%; min-height:400px; }}\n.chart .modebar {{ left: 0 !important; right: auto !important; }}\n@media (max-width:768px) {{ .sidebar {{ display:none; }} .main {{ margin-left:0; }} }}\n::-webkit-scrollbar {{ width:6px; }} ::-webkit-scrollbar-track {{ background:transparent; }}\n::-webkit-scrollbar-thumb {{ background:var(--border); border-radius:3px; }}\n</style>\n</head>\n<body>\n\n<header class=\"header\">\n  <div class=\"header-logo\"><div class=\"icon\">D</div><span>Dispenso Benchmarks</span></div>\n  <div class=\"header-right\">\n    <select class=\"platform-select\" id=\"platformSelect\" onchange=\"switchPlatform(this.value)\"></select>\n    <button class=\"btn\" onclick=\"toggleTheme()\" id=\"themeBtn\">Light</button>\n  </div>\n</header>\n\n<nav class=\"sidebar\">\n  <div class=\"search-box\"><input type=\"text\" class=\"search-input\" placeholder=\"Filter...\" oninput=\"filterNav(this.value)\"></div>\n  <div class=\"nav-section-title\">Benchmark Suites</div>\n  {nav_items}\n</nav>\n\n<main class=\"main\">\n  <div class=\"info-cards\" id=\"infoCards\"></div>\n  <div class=\"stats-bar\" id=\"statsBar\"></div>\n  <div id=\"chartSections\"></div>\n</main>\n\n<script>\nconst PLATFORMS = {platforms_json};\nlet currentPlatformIdx = 0;\nlet currentTheme = 'dark';\n\n// ─── Time unit helpers ─────────────────────────────────────────\nfunction autoUnit(maxNs) {{\n  if (maxNs >= 1e9) return {{ scale: 1e9, label: 's' }};\n  if (maxNs >= 1e6) return {{ scale: 1e6, label: 'ms' }};\n  if (maxNs >= 1e3) return {{ scale: 1e3, label: 'us' }};\n  return {{ scale: 1, label: 'ns' }};\n}}\n\n// ─── Theme ─────────────────────────────────────────────────────\nfunction themeLayout() {{\n  const dark = currentTheme === 'dark';\n  return {{\n    paper_bgcolor: dark ? '#1c2128' : '#fff',\n    plot_bgcolor: dark ? '#0d1117' : '#f6f8fa',\n    font: {{ color: dark ? '#e6edf3' : '#1f2328', family: '-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif', size: 12 }},\n    xaxis: {{ gridcolor: dark ? '#21262d' : '#eaeef2', zerolinecolor: dark ? '#30363d' : '#d0d7de' }},\n    yaxis: {{ gridcolor: dark ? '#21262d' : '#eaeef2', zerolinecolor: dark ? '#30363d' : '#d0d7de' }},\n    legend: {{ bgcolor: dark ? 'rgba(22,27,34,0.9)' : 'rgba(255,255,255,0.95)', bordercolor: dark ? '#30363d' : '#d0d7de', borderwidth: 1 }},\n    modebar: {{ orientation: 'h', bgcolor: 'transparent', activecolor: dark ? '#58a6ff' : '#0969da' }},\n  }};\n}}\n\nconst plotlyConfig = {{ responsive: true, scrollZoom: true, displayModeBar: true, modeBarButtonsToRemove: ['lasso2d','select2d'], displaylogo: false }};\n\n// Pin the time axis lower bound to zero on any zoom/pan.\n// Preserves the zoom span so repeated zoom in/out doesn't drift.\nfunction pinZeroAxis(chartId, axis) {{\n  const el = document.getElementById('chart-' + chartId);\n  if (!el) return;\n  let pinning = false;\n  el.on('plotly_relayout', function(ed) {{\n    if (pinning) return;\n    const key0 = axis + '.range[0]';\n    const key1 = axis + '.range[1]';\n    // Check if the lower bound moved away from zero\n    if (key0 in ed && ed[key0] !== 0) {{\n      const lo = ed[key0];\n      const hi = key1 in ed ? ed[key1] : el.layout[axis].range[1];\n      const span = hi - lo;  // preserve intended zoom level\n      pinning = true;\n      Plotly.relayout(el, {{ [key0]: 0, [key1]: span }}).then(() => {{ pinning = false; }});\n    }}\n  }});\n}}\n\n// ─── Renderers ─────────────────────────────────────────────────\nfunction renderLine(cfg) {{\n  const allY = cfg.traces.flatMap(t => t.baseline ? [] : t.y);  // exclude serial baseline\n  const maxY = allY.length > 0 ? Math.max(...allY) : 1;\n  const u = autoUnit(maxY);\n  const scaledAll = allY.map(v => v / u.scale);\n\n  // Auto-zoom: compare per-trace medians to detect when one trace dominates\n  const traceMedians = cfg.traces.filter(t => !t.baseline).map(t => {{\n    const sv = [...t.y].filter(v => v > 0).sort((a,b) => a - b);\n    return sv.length > 0 ? sv[Math.floor(sv.length / 2)] / u.scale : 0;\n  }}).filter(v => v > 0).sort((a,b) => a - b);\n  const maxTraceMedian = traceMedians.length > 0 ? traceMedians[traceMedians.length - 1] : 1;\n  const minTraceMedian = traceMedians.length > 0 ? traceMedians[0] : 1;\n  const autoZoom = !cfg.no_auto_zoom && traceMedians.length >= 2 && maxTraceMedian / minTraceMedian > 5;\n  // Zoom to show the competitive traces: 3x the second-highest trace median\n  const secondMax = traceMedians.length >= 2 ? traceMedians[traceMedians.length - 2] : maxTraceMedian;\n  const zoomMax = secondMax * 3;\n\n  const traces = cfg.traces.map(t => ({{\n    x: t.x, y: t.y.map(v => v / u.scale), name: t.name,\n    type: 'scatter', mode: t.baseline ? 'lines' : 'lines+markers',\n    line: {{ color: t.color, width: t.baseline ? 1.5 : 2.5, dash: t.dash || 'solid' }},\n    marker: {{ size: t.baseline ? 0 : 5 }},\n    hovertemplate: '%{{x}} threads: %{{y:.4g}} ' + u.label + '<extra>%{{fullData.name}}</extra>',\n  }}));\n\n  // Add invisible legend entries for skipped (cannot-complete) libraries\n  const skipped = cfg.skipped_libs || [];\n  for (const sl of skipped) {{\n    traces.push({{\n      x: [null], y: [null], name: sl.name + ' (CANNOT COMPLETE)',\n      type: 'scatter', mode: 'markers',\n      marker: {{ size: 12, color: sl.color, symbol: 'x', line: {{ width: 2, color: sl.color }} }},\n      hoverinfo: 'name',\n      showlegend: true,\n    }});\n  }}\n\n  const tl = themeLayout();\n  // Add text annotation when libraries are skipped\n  const annotations = [];\n  if (skipped.length > 0) {{\n    const names = skipped.map(s => s.name).join(', ');\n    annotations.push({{\n      text: names + ': cannot complete (out of memory)',\n      xref: 'paper', yref: 'paper', x: 0.5, y: -0.12,\n      showarrow: false,\n      font: {{ size: 11, color: skipped.length === 1 ? skipped[0].color : '#e74c3c' }},\n    }});\n  }}\n  const layout = {{\n    ...tl, title: {{ text: cfg.title + (autoZoom ? ' (auto-zoomed, double-click to reset)' : ''), font: {{ size: 14 }} }},\n    xaxis: {{ ...tl.xaxis, title: cfg.xaxis || 'Threads', fixedrange: true }},\n    yaxis: {{ ...tl.yaxis, title: 'Time (' + u.label + ')', rangemode: 'tozero',\n              ...(autoZoom ? {{ range: [0, zoomMax] }} : {{}}) }},\n    legend: {{ ...tl.legend, orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1 }},\n    margin: {{ l: 60, r: 20, t: 50, b: skipped.length > 0 ? 70 : 50 }}, hovermode: 'x unified',\n    ...(annotations.length > 0 ? {{ annotations }} : {{}}),\n  }};\n  Plotly.newPlot('chart-' + cfg.id, traces, layout, plotlyConfig);\n  pinZeroAxis(cfg.id, 'yaxis');\n}}\n\nfunction renderGroupedBarH(cfg) {{\n  const allV = cfg.groups.flatMap(g => g.values);\n  const maxV = Math.max(...allV.filter(v => v > 0));\n  const u = autoUnit(maxV);\n  const useLog = cfg.log_scale && maxV / Math.min(...allV.filter(v => v > 0)) > 50;\n  // Reverse so first category is at top\n  const cats = [...cfg.categories].reverse();\n  const traces = cfg.groups.map(g => ({{\n    type: 'bar', orientation: 'h', name: g.name,\n    y: cats, x: [...g.values].reverse().map(v => useLog ? v : v / u.scale),\n    marker: {{ color: g.color, opacity: 0.85 }},\n    hovertemplate: useLog\n      ? '%{{y}}: %{{x:.4g}} ns<extra>%{{fullData.name}}</extra>'\n      : '%{{y}}: %{{x:.4g}} ' + u.label + '<extra>%{{fullData.name}}</extra>',\n  }}));\n  const tl = themeLayout();\n  const el = document.getElementById('chart-' + cfg.id);\n  if (el) el.style.minHeight = Math.max(350, cfg.categories.length * 40 + 100) + 'px';\n  Plotly.newPlot('chart-' + cfg.id, traces, {{\n    ...tl, barmode: 'group', bargap: 0.15, bargroupgap: 0.1,\n    title: {{ text: cfg.title, font: {{ size: 14 }} }},\n    xaxis: {{ ...tl.xaxis, title: useLog ? 'Time (ns) - log scale' : 'Time (' + u.label + ')',\n              type: useLog ? 'log' : 'linear' }},\n    yaxis: {{ ...tl.yaxis, automargin: true, fixedrange: true }},\n    legend: {{ ...tl.legend, orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1 }},\n    margin: {{ l: 180, r: 20, t: 60, b: 50 }},\n  }}, plotlyConfig);\n  if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n}}\n\nfunction renderGroupedBarV(cfg) {{\n  const allV = cfg.groups.flatMap(g => g.values);\n  const maxV = Math.max(...allV.filter(v => v > 0));\n  const u = autoUnit(maxV);\n\n  // Auto-zoom: compare per-group MAX values to detect outlier groups.\n  // Using max (not median) ensures we don't clip the tallest competitive bars.\n  // Exclude error-placeholder values from zoom calculation.\n  const groupMaxes = cfg.groups.map(g => {{\n    const errSet = new Set(g.error_indices || []);\n    const pos = g.values.filter((v, i) => v > 0 && !errSet.has(i));\n    return pos.length > 0 ? Math.max(...pos) : 0;\n  }}).filter(v => v > 0).sort((a,b) => a - b);\n  const maxGroupMax = groupMaxes.length > 0 ? groupMaxes[groupMaxes.length - 1] : 1;\n  const secondGroupMax = groupMaxes.length >= 2 ? groupMaxes[groupMaxes.length - 2] : maxGroupMax;\n  const autoZoom = groupMaxes.length >= 2 && maxGroupMax / secondGroupMax > 5;\n  const zoomMax = (secondGroupMax * 1.5) / u.scale;\n\n  const traces = cfg.groups.map(g => {{\n    const n = g.values.length;\n    const errSet = new Set(g.error_indices || []);\n    const hasErrors = errSet.size > 0;\n\n    // Per-bar colors and patterns for error bars\n    const colors = g.values.map((_, i) => errSet.has(i) ? 'rgba(200,200,200,0.25)' : g.color);\n    const patterns = hasErrors ? {{\n      shape: g.values.map((_, i) => errSet.has(i) ? '/' : ''),\n      fgcolor: g.values.map((_, i) => errSet.has(i) ? '#e74c3c' : g.color),\n      solidity: 0.4,\n    }} : undefined;\n    // Custom hover: show \"CANNOT COMPLETE\" for error bars\n    const customdata = g.values.map((_, i) => errSet.has(i) ? 'CANNOT COMPLETE' : '');\n    const hovertemplate = g.values.map((_, i) =>\n      errSet.has(i)\n        ? '%{{x}}: <b>CANNOT COMPLETE</b><extra>' + g.name + '</extra>'\n        : '%{{x}}: %{{y:.4g}} ' + u.label + '<extra>' + g.name + '</extra>'\n    );\n\n    return {{\n      type: 'bar', name: g.name,\n      x: cfg.categories, y: g.values.map(v => v / u.scale),\n      marker: {{ color: colors, opacity: 0.85, ...(patterns ? {{ pattern: patterns }} : {{}}) }},\n      customdata, hovertemplate,\n      // Text label inside error bars\n      text: g.values.map((_, i) => errSet.has(i) ? 'CANNOT<br>COMPLETE' : ''),\n      textposition: 'inside', insidetextanchor: 'middle', textangle: -90,\n      textfont: {{ color: '#e74c3c', size: 11 }},\n    }};\n  }});\n  const tl = themeLayout();\n  Plotly.newPlot('chart-' + cfg.id, traces, {{\n    ...tl, barmode: 'group', bargap: 0.2,\n    title: {{ text: cfg.title + (autoZoom ? ' (auto-zoomed, double-click to reset)' : ''), font: {{ size: 14 }} }},\n    xaxis: {{ ...tl.xaxis, title: cfg.xaxis || '', fixedrange: true }},\n    yaxis: {{ ...tl.yaxis, title: 'Time (' + u.label + ')', rangemode: 'tozero',\n              ...(autoZoom ? {{ range: [0, zoomMax] }} : {{}}) }},\n    legend: {{ ...tl.legend, title: {{ text: 'Implementation' }} }},\n    margin: {{ l: 60, r: 20, t: 50, b: 50 }},\n  }}, plotlyConfig);\n  pinZeroAxis(cfg.id, 'yaxis');\n}}\n\nfunction renderBarHColored(cfg) {{\n  const maxV = Math.max(...cfg.items.map(i => i.time_ns));\n  const minV = Math.min(...cfg.items.filter(i => i.time_ns > 0).map(i => i.time_ns));\n  const u = autoUnit(maxV);\n  const useLog = maxV / minV > 100;\n  // Reverse for top-to-bottom display\n  const items = [...cfg.items].reverse();\n  const trace = {{\n    type: 'bar', orientation: 'h',\n    y: items.map(i => i.name), x: items.map(i => useLog ? i.time_ns : i.time_ns / u.scale),\n    marker: {{ color: items.map(i => i.color), opacity: 0.85 }},\n    hovertemplate: useLog\n      ? '%{{y}}: %{{x:.4g}} ns<extra></extra>'\n      : '%{{y}}: %{{x:.4g}} ' + u.label + '<extra></extra>',\n  }};\n  const tl = themeLayout();\n  const el = document.getElementById('chart-' + cfg.id);\n  if (el) el.style.minHeight = Math.max(350, cfg.items.length * 24 + 100) + 'px';\n\n  const layout = {{\n    ...tl, showlegend: false,\n    title: {{ text: cfg.title, font: {{ size: 14 }} }},\n    xaxis: {{ ...tl.xaxis, title: useLog ? 'Time (ns) - log scale' : 'Time (' + u.label + ')',\n              type: useLog ? 'log' : 'linear' }},\n    yaxis: {{ ...tl.yaxis, automargin: true, tickfont: {{ size: 10 }}, fixedrange: true }},\n    margin: {{ l: 250, r: 20, t: 50, b: 50 }}, bargap: 0.3,\n  }};\n\n  // Add manual legend if provided\n  if (cfg.legend) {{\n    layout.showlegend = true;\n    // Add invisible traces for legend\n    const traces = [trace];\n    cfg.legend.forEach(l => {{\n      traces.push({{\n        type: 'bar', orientation: 'h', x: [null], y: [null],\n        marker: {{ color: l.color }}, name: l.name, showlegend: true,\n      }});\n    }});\n    trace.showlegend = false;\n    Plotly.newPlot('chart-' + cfg.id, traces, layout, plotlyConfig);\n    if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n    return;\n  }}\n  Plotly.newPlot('chart-' + cfg.id, [trace], layout, plotlyConfig);\n  if (!useLog) pinZeroAxis(cfg.id, 'xaxis');\n}}\n\nfunction renderGroupedBarHError(cfg) {{\n  // Reverse for top-to-bottom\n  const cats = [...cfg.categories].reverse();\n  const traces = cfg.groups.map(g => {{\n    const vals = [...g.values].reverse();\n    const errs = [...g.errors].reverse();\n    // Clamp lower error bars so they don't go below zero (scheduling error can't be negative)\n    const errMinus = vals.map((v, i) => Math.min(errs[i], v));\n    return {{\n      type: 'bar', orientation: 'h', name: g.name,\n      y: cats, x: vals,\n      error_x: {{ type: 'data', array: errs, arrayminus: errMinus, visible: true }},\n      marker: {{ color: g.color, opacity: 0.85 }},\n      hovertemplate: '%{{y}}: %{{x:.2f}} +/- %{{error_x.array:.2f}} us<extra>%{{fullData.name}}</extra>',\n    }};\n  }});\n  const tl = themeLayout();\n  Plotly.newPlot('chart-' + cfg.id, traces, {{\n    ...tl, barmode: 'group', bargap: 0.2,\n    title: {{ text: cfg.title, font: {{ size: 14 }} }},\n    xaxis: {{ ...tl.xaxis, title: cfg.xaxis_label || 'Mean Error (us)' }},\n    yaxis: {{ ...tl.yaxis, automargin: true, fixedrange: true }},\n    legend: {{ ...tl.legend }},\n    margin: {{ l: 200, r: 20, t: 50, b: 50 }},\n  }}, plotlyConfig);\n  pinZeroAxis(cfg.id, 'xaxis');\n}}\n\nfunction renderChart(cfg) {{\n  switch (cfg.type) {{\n    case 'line': renderLine(cfg); break;\n    case 'grouped_bar_h': renderGroupedBarH(cfg); break;\n    case 'grouped_bar_v': renderGroupedBarV(cfg); break;\n    case 'bar_h_colored': renderBarHColored(cfg); break;\n    case 'grouped_bar_h_error': renderGroupedBarHError(cfg); break;\n  }}\n}}\n\n// ─── Platform switching ────────────────────────────────────────\nfunction buildInfoCards(machine) {{\n  const compiler = machine.compiler || {{}};\n  document.getElementById('infoCards').innerHTML = `\n    <div class=\"info-card\"><div class=\"label\">Platform</div><div class=\"value\">${{machine.platform}} ${{machine.architecture||''}}</div><div class=\"detail\">${{machine.platform_release||''}}</div></div>\n    <div class=\"info-card\"><div class=\"label\">Processor</div><div class=\"value\">${{machine.cpu_model}}</div><div class=\"detail\">${{machine.cpu_cores}} cores &middot; ${{Math.round(machine.memory_gb||0)}} GB RAM</div></div>\n    <div class=\"info-card\"><div class=\"label\">Compiler</div><div class=\"value\">${{compiler.compiler_summary||'Unknown'}}</div><div class=\"detail\">C++${{compiler.cxx_standard||'??'}} &middot; ${{compiler.build_type||''}}</div></div>\n    <div class=\"info-card\"><div class=\"label\">Run Date</div><div class=\"value\">${{(machine.timestamp||'').slice(0,10)}}</div><div class=\"detail\">${{(machine.timestamp||'').slice(11,19)}}</div></div>\n  `;\n}}\n\nfunction buildSections(charts) {{\n  // Group by suite\n  const suites = new Map();\n  charts.forEach(c => {{\n    if (!suites.has(c.suite)) suites.set(c.suite, []);\n    suites.get(c.suite).push(c);\n  }});\n\n  let html = '';\n  suites.forEach((chartList, suite) => {{\n    const display = suite.replace(/_/g, ' ').replace(/\\\\b\\\\w/g, l => l.toUpperCase());\n    html += `<section id=\"section-${{suite}}\" class=\"benchmark-section\"><h2 class=\"section-title\">${{display}}</h2>`;\n    chartList.forEach(c => {{\n      html += `<div class=\"chart-container\"><div id=\"chart-${{c.id}}\" class=\"chart\"></div></div>`;\n    }});\n    html += '</section>';\n  }});\n  document.getElementById('chartSections').innerHTML = html;\n}}\n\nfunction switchPlatform(idx) {{\n  currentPlatformIdx = parseInt(idx);\n  const p = PLATFORMS[currentPlatformIdx];\n  buildInfoCards(p.machine);\n  document.getElementById('statsBar').innerHTML = `\n    <div class=\"stat-item\"><span class=\"stat-dot info\"></span><span>Suites: <strong>${{new Set(p.charts.map(c=>c.suite)).size}}</strong></span></div>\n    <div class=\"stat-item\"><span class=\"stat-dot ok\"></span><span>Charts: <strong>${{p.charts.length}}</strong></span></div>\n  `;\n  buildSections(p.charts);\n  // Small delay so DOM is ready\n  requestAnimationFrame(() => {{\n    p.charts.forEach(renderChart);\n    observeSections();\n  }});\n}}\n\nfunction toggleTheme() {{\n  currentTheme = currentTheme === 'dark' ? 'light' : 'dark';\n  document.documentElement.setAttribute('data-theme', currentTheme);\n  document.getElementById('themeBtn').textContent = currentTheme === 'dark' ? 'Light' : 'Dark';\n  const p = PLATFORMS[currentPlatformIdx];\n  p.charts.forEach(renderChart);\n}}\n\nfunction filterNav(q) {{\n  q = q.toLowerCase();\n  document.querySelectorAll('.nav-link').forEach(l => {{\n    l.style.display = l.textContent.toLowerCase().includes(q) ? 'block' : 'none';\n  }});\n}}\n\nlet observer;\nfunction observeSections() {{\n  if (observer) observer.disconnect();\n  observer = new IntersectionObserver(entries => {{\n    entries.forEach(e => {{\n      if (e.isIntersecting) {{\n        const id = e.target.id.replace('section-', '');\n        document.querySelectorAll('.nav-link').forEach(l => {{\n          l.classList.toggle('active', l.dataset.suite === id);\n        }});\n      }}\n    }});\n  }}, {{ rootMargin: '-20% 0px -70% 0px' }});\n  document.querySelectorAll('.benchmark-section').forEach(s => observer.observe(s));\n}}\n\n// ─── Init ──────────────────────────────────────────────────────\nconst sel = document.getElementById('platformSelect');\nPLATFORMS.forEach((p, i) => {{\n  const opt = document.createElement('option');\n  opt.value = i; opt.textContent = p.label;\n  sel.appendChild(opt);\n}});\nswitchPlatform(0);\n</script>\n</body>\n</html>\n\"\"\"\n\n    with open(output_path, \"w\") as f:\n        f.write(html)\n    print(f\"Generated: {output_path}\")\n\n\n# ─── Main ───────────────────────────────────────────────────────────────────\n\n\ndef load_platform(json_path):\n    \"\"\"Load a JSON file and build chart configs.\"\"\"\n    with open(json_path) as f:\n        data = json.load(f)\n\n    machine = data[\"machine_info\"]\n    platform_id = machine.get(\"platform_id\", Path(json_path).stem)\n    label = (\n        f\"{machine.get('cpu_model', 'Unknown')} ({machine.get('cpu_cores', '?')} cores)\"\n    )\n\n    charts = []\n    for result in data[\"results\"]:\n        if not result.get(\"success\") or \"data\" not in result:\n            continue\n        suite = result[\"name\"].replace(\".exe\", \"\").replace(\"_benchmark\", \"\")\n        benchmarks = result[\"data\"].get(\"benchmarks\", [])\n        charts.extend(build_charts_for_suite(benchmarks, suite))\n\n    return {\n        \"id\": platform_id,\n        \"label\": label,\n        \"machine\": machine,\n        \"charts\": charts,\n    }\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Generate interactive benchmark dashboard\"\n    )\n    parser.add_argument(\"inputs\", nargs=\"+\", type=Path, help=\"Benchmark JSON file(s)\")\n    parser.add_argument(\n        \"-o\",\n        \"--output\",\n        type=Path,\n        default=Path(\"/tmp/dispenso-benchmarks.html\"),\n        help=\"Output HTML file\",\n    )\n    args = parser.parse_args()\n\n    platforms = []\n    for path in args.inputs:\n        print(f\"Loading: {path}\")\n        platforms.append(load_platform(path))\n        print(\n            f\"  Platform: {platforms[-1]['label']}, Charts: {len(platforms[-1]['charts'])}\"\n        )\n\n    generate_html(platforms, args.output)\n    print(f\"\\nTotal platforms: {len(platforms)}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/run_benchmarks.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"\nBenchmark runner for dispenso.\n\nThis script discovers and runs the dispenso benchmarks, collecting results\ninto a JSON file that includes machine information for reproducibility.\n\nUsage:\n    python run_benchmarks.py                          # run only (existing build)\n    python run_benchmarks.py --build                  # build + run all\n    python run_benchmarks.py --build -B pipeline      # build + run matching\n    python run_benchmarks.py --build --cmake-args=\"-DCMAKE_CXX_COMPILER=g++-13\"\n\nThe output JSON can then be processed by generate_charts.py to create\nvisualizations and reports.\n\nRequirements:\n    None (matplotlib/pandas only needed for generate_charts.py)\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport platform\nimport re\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Any, Dict, List, Optional\n\nSCRIPT_DIR = Path(__file__).parent\nDEFAULT_SOURCE_DIR = SCRIPT_DIR.parent\nDEFAULT_BUILD_DIR = Path(tempfile.gettempdir()) / \"dispenso-build\"\n\n\ndef get_machine_info() -> Dict[str, Any]:\n    \"\"\"Gather machine information for benchmark context.\"\"\"\n    info = {\n        \"timestamp\": datetime.now().isoformat(),\n        \"platform\": platform.system(),\n        \"platform_release\": platform.release(),\n        \"platform_version\": platform.version(),\n        \"architecture\": platform.machine(),\n        \"processor\": platform.processor(),\n        \"python_version\": platform.python_version(),\n    }\n\n    # Try to get more detailed CPU info\n    if platform.system() == \"Linux\":\n        try:\n            with open(\"/proc/cpuinfo\", \"r\") as f:\n                cpuinfo = f.read()\n            # Extract model name\n            match = re.search(r\"model name\\s*:\\s*(.+)\", cpuinfo)\n            if match:\n                info[\"cpu_model\"] = match.group(1).strip()\n            # Count cores\n            info[\"cpu_cores\"] = cpuinfo.count(\"processor\\t:\")\n            # Get cache info\n            match = re.search(r\"cache size\\s*:\\s*(.+)\", cpuinfo)\n            if match:\n                info[\"cache_size\"] = match.group(1).strip()\n        except Exception as e:\n            info[\"cpu_info_error\"] = str(e)\n\n        # Memory info\n        try:\n            with open(\"/proc/meminfo\", \"r\") as f:\n                meminfo = f.read()\n            match = re.search(r\"MemTotal:\\s*(\\d+)\", meminfo)\n            if match:\n                info[\"memory_kb\"] = int(match.group(1))\n                info[\"memory_gb\"] = round(int(match.group(1)) / 1024 / 1024, 1)\n        except Exception:\n            pass\n\n    elif platform.system() == \"Darwin\":  # macOS\n        try:\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"machdep.cpu.brand_string\"],\n                capture_output=True,\n                text=True,\n            )\n            if result.returncode == 0:\n                info[\"cpu_model\"] = result.stdout.strip()\n\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"hw.ncpu\"], capture_output=True, text=True\n            )\n            if result.returncode == 0:\n                info[\"cpu_cores\"] = int(result.stdout.strip())\n\n            result = subprocess.run(\n                [\"sysctl\", \"-n\", \"hw.memsize\"], capture_output=True, text=True\n            )\n            if result.returncode == 0:\n                mem_bytes = int(result.stdout.strip())\n                info[\"memory_gb\"] = round(mem_bytes / 1024 / 1024 / 1024, 1)\n        except Exception as e:\n            info[\"cpu_info_error\"] = str(e)\n\n    elif platform.system() == \"Windows\":\n        try:\n            import winreg\n\n            key = winreg.OpenKey(\n                winreg.HKEY_LOCAL_MACHINE,\n                r\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\",\n            )\n            info[\"cpu_model\"] = winreg.QueryValueEx(key, \"ProcessorNameString\")[0]\n            winreg.CloseKey(key)\n        except Exception:\n            pass\n\n        try:\n            result = subprocess.run(\n                [\"wmic\", \"computersystem\", \"get\", \"totalphysicalmemory\"],\n                capture_output=True,\n                text=True,\n            )\n            lines = result.stdout.strip().split(\"\\n\")\n            if len(lines) > 1:\n                mem_bytes = int(lines[1].strip())\n                info[\"memory_gb\"] = round(mem_bytes / 1024 / 1024 / 1024, 1)\n        except Exception:\n            pass\n\n        info[\"cpu_cores\"] = os.cpu_count()\n\n    return info\n\n\ndef generate_platform_id(machine_info: Dict[str, Any]) -> str:\n    \"\"\"Generate a human-readable platform identifier from machine info.\n\n    Examples: linux-threadripper-96c, macos-m4-12c, windows-zen4-24c\n    \"\"\"\n    system = machine_info.get(\"platform\", \"unknown\").lower()\n    if system == \"darwin\":\n        system = \"macos\"\n\n    cpu_model = machine_info.get(\"cpu_model\", \"\")\n    cores = machine_info.get(\"cpu_cores\", os.cpu_count() or 0)\n    model_lower = cpu_model.lower()\n\n    # Extract CPU family identifier\n    cpu_id = \"unknown\"\n    if system == \"macos\":\n        # Apple Silicon: \"Apple M4\", \"Apple M2 Pro\", etc.\n        match = re.search(r\"apple\\s+(m\\d+(?:\\s+\\w+)?)\", model_lower)\n        if match:\n            cpu_id = match.group(1).replace(\" \", \"-\")\n    elif \"threadripper\" in model_lower:\n        cpu_id = \"threadripper\"\n    elif \"epyc\" in model_lower:\n        cpu_id = \"epyc\"\n    elif \"ryzen\" in model_lower:\n        match = re.search(r\"ryzen\\s+(\\d+)\\s+(\\d{4})\", model_lower)\n        if match:\n            cpu_id = f\"ryzen{match.group(1)}-{match.group(2)}\"\n        else:\n            cpu_id = \"ryzen\"\n    elif \"xeon\" in model_lower:\n        cpu_id = \"xeon\"\n    elif re.search(r\"core.*i\\d\", model_lower):\n        match = re.search(r\"i(\\d+)-(\\d+)\", model_lower)\n        if match:\n            cpu_id = f\"i{match.group(1)}-{match.group(2)}\"\n        else:\n            cpu_id = \"core\"\n    elif \"zen\" in model_lower:\n        match = re.search(r\"zen\\s*(\\d+)\", model_lower)\n        if match:\n            cpu_id = f\"zen{match.group(1)}\"\n\n    return f\"{system}-{cpu_id}-{cores}c\"\n\n\ndef _parse_cmake_cache(cache_path: Path, var_map: list) -> Dict[str, str]:\n    \"\"\"Parse CMakeCache.txt for specified variables.\n\n    Args:\n        cache_path: Path to CMakeCache.txt\n        var_map: List of (cmake_var, label) tuples\n\n    Returns:\n        Dict mapping labels to their values.\n    \"\"\"\n    info: Dict[str, str] = {}\n    try:\n        cache = cache_path.read_text()\n        for var, label in var_map:\n            match = re.search(rf\"^{re.escape(var)}:\\w+=(.+)\", cache, re.MULTILINE)\n            if match:\n                val = match.group(1).strip()\n                if val:\n                    info[label] = val\n    except Exception:\n        pass\n    return info\n\n\ndef _parse_compiler_cmake(cmake_files_dir: Path, var_map: list) -> Dict[str, str]:\n    \"\"\"Parse CMakeCXXCompiler.cmake for compiler ID and version.\n\n    Args:\n        cmake_files_dir: Path to CMakeFiles/ directory\n        var_map: List of (cmake_var, label) tuples to look for\n\n    Returns:\n        Dict mapping labels to their values.\n    \"\"\"\n    info: Dict[str, str] = {}\n    if not cmake_files_dir.is_dir():\n        return info\n    for child in cmake_files_dir.iterdir():\n        compiler_cmake = child / \"CMakeCXXCompiler.cmake\"\n        if compiler_cmake.exists():\n            try:\n                text = compiler_cmake.read_text()\n                for var, label in var_map:\n                    match = re.search(rf'set\\({re.escape(var)}\\s+\"([^\"]+)\"\\)', text)\n                    if match:\n                        info[label] = match.group(1)\n            except Exception:\n                pass\n            break\n    return info\n\n\ndef _build_compiler_summary(info: Dict[str, str]) -> str:\n    \"\"\"Assemble a human-readable compiler summary string.\"\"\"\n    parts = []\n    if \"compiler_id\" in info:\n        parts.append(info[\"compiler_id\"])\n    if \"compiler_version\" in info:\n        parts.append(info[\"compiler_version\"])\n    if \"build_type\" in info:\n        parts.append(info[\"build_type\"])\n    if \"cxx_standard\" in info:\n        parts.append(f\"C++{info['cxx_standard']}\")\n    return \" \".join(parts) if parts else \"\"\n\n\ndef get_compiler_info(build_dir: Path) -> Dict[str, str]:\n    \"\"\"Detect compiler and build settings from the CMake build directory.\"\"\"\n    # Locate the cmake build root (handle build_dir pointing at bin/)\n    cmake_root = None\n    for candidate in [build_dir, build_dir.parent]:\n        if (candidate / \"CMakeCache.txt\").exists():\n            cmake_root = candidate\n            break\n\n    if cmake_root is None:\n        return {}\n\n    # Parse CMakeCache.txt for build settings & compiler path\n    cache_vars = [\n        (\"CMAKE_CXX_COMPILER\", \"compiler_path\"),\n        (\"CMAKE_CXX_COMPILER_ID\", \"compiler_id\"),\n        (\"CMAKE_CXX_COMPILER_VERSION\", \"compiler_version\"),\n        (\"CMAKE_BUILD_TYPE\", \"build_type\"),\n        (\"CMAKE_CXX_STANDARD\", \"cxx_standard\"),\n        (\"CMAKE_CXX_FLAGS\", \"cxx_flags\"),\n    ]\n    info = _parse_cmake_cache(cmake_root / \"CMakeCache.txt\", cache_vars)\n\n    # Fall back to CMakeCXXCompiler.cmake for compiler ID & version\n    if \"compiler_id\" not in info or \"compiler_version\" not in info:\n        id_version_vars = [\n            (\"CMAKE_CXX_COMPILER_ID\", \"compiler_id\"),\n            (\"CMAKE_CXX_COMPILER_VERSION\", \"compiler_version\"),\n        ]\n        # Only fill missing values\n        fallback = _parse_compiler_cmake(cmake_root / \"CMakeFiles\", id_version_vars)\n        for label, val in fallback.items():\n            if label not in info:\n                info[label] = val\n\n    summary = _build_compiler_summary(info)\n    if summary:\n        info[\"compiler_summary\"] = summary\n\n    return info\n\n\ndef _discover_benchmark_targets(build_dir: Path, pattern: str) -> List[str]:\n    \"\"\"Discover benchmark targets matching a regex pattern.\n\n    Uses cmake --build --target help to list available targets, then filters\n    for benchmark targets matching the pattern.  Returns an empty list if\n    target discovery fails (caller should fall back to building all).\n    \"\"\"\n    try:\n        result = subprocess.run(\n            [\"cmake\", \"--build\", str(build_dir), \"--target\", \"help\"],\n            capture_output=True,\n            text=True,\n        )\n        if result.returncode != 0:\n            return []\n\n        targets = []\n        for line in result.stdout.splitlines():\n            line = line.strip()\n            if \"benchmark\" not in line.lower():\n                continue\n            # cmake --target help format: \"... target_name\" (Makefiles)\n            # or just \"target_name\" (Ninja)\n            match = re.search(r\"(?:\\.\\.\\.\\s+)?(\\S*benchmark\\S*)\", line, re.IGNORECASE)\n            if match:\n                target = match.group(1)\n                if re.search(pattern, target):\n                    targets.append(target)\n        return targets\n    except Exception:\n        return []\n\n\ndef configure_and_build(\n    source_dir: Path,\n    build_dir: Path,\n    jobs: int,\n    clean: bool = False,\n    benchmark_filter: Optional[str] = None,\n    extra_cmake_args: Optional[List[str]] = None,\n) -> bool:\n    \"\"\"Configure and build dispenso benchmarks.\n\n    Args:\n        source_dir: Path to dispenso source root.\n        build_dir: Path to cmake build directory.\n        jobs: Number of parallel build jobs.\n        clean: If True, wipe build_dir before configuring.\n        benchmark_filter: If set, attempt to build only matching benchmark targets.\n        extra_cmake_args: Additional cmake flags (e.g., -DCMAKE_CXX_COMPILER=g++-13).\n            Pass -G \"generator\" here to override CMake's default generator.\n\n    Returns:\n        True on success, False on failure.\n    \"\"\"\n    if clean and build_dir.exists():\n        print(f\"Cleaning build directory: {build_dir}\")\n        shutil.rmtree(build_dir)\n\n    build_dir.mkdir(parents=True, exist_ok=True)\n\n    # Configure\n    cmake_cmd = [\n        \"cmake\",\n        \"-S\",\n        str(source_dir),\n        \"-B\",\n        str(build_dir),\n        \"-DDISPENSO_BUILD_BENCHMARKS=ON\",\n        \"-DCMAKE_BUILD_TYPE=Release\",\n        \"-DCMAKE_CXX_STANDARD=20\",\n    ]\n\n    if extra_cmake_args:\n        cmake_cmd.extend(extra_cmake_args)\n\n    print(\"Configuring cmake...\")\n    print(f\"  Source: {source_dir}\")\n    print(f\"  Build:  {build_dir}\")\n    print(f\"  Flags:  {' '.join(cmake_cmd[2:])}\")\n    sys.stdout.flush()\n\n    result = subprocess.run(cmake_cmd)\n    if result.returncode != 0:\n        print(\"Error: cmake configure failed\")\n        return False\n\n    # Build\n    if benchmark_filter:\n        targets = _discover_benchmark_targets(build_dir, benchmark_filter)\n        if targets:\n            print(f\"Building {len(targets)} matching target(s): {', '.join(targets)}\")\n            sys.stdout.flush()\n            for target in targets:\n                target_cmd = [\n                    \"cmake\",\n                    \"--build\",\n                    str(build_dir),\n                    \"--target\",\n                    target,\n                    f\"-j{jobs}\",\n                    \"--config\",\n                    \"Release\",\n                ]\n                result = subprocess.run(target_cmd)\n                if result.returncode != 0:\n                    print(f\"Error: build failed for target {target}\")\n                    return False\n            return True\n        else:\n            print(\"No matching targets discovered, building all...\")\n\n    print(f\"Building with {jobs} parallel job(s)...\")\n    sys.stdout.flush()\n    build_cmd = [\n        \"cmake\",\n        \"--build\",\n        str(build_dir),\n        f\"-j{jobs}\",\n        \"--config\",\n        \"Release\",\n    ]\n    result = subprocess.run(build_cmd)\n    if result.returncode != 0:\n        print(\"Error: build failed\")\n        return False\n\n    return True\n\n\ndef find_benchmarks(build_dir: Path, pattern: Optional[str] = None) -> List[Path]:\n    \"\"\"Find benchmark executables in the build directory.\"\"\"\n    benchmarks = []\n\n    # Search common locations and multi-config subdirectories (Release, Debug, etc.)\n    _config_subdirs = [\"Release\", \"RelWithDebInfo\", \"Debug\", \"MinSizeRel\"]\n    search_paths = []\n    for base in [build_dir / \"bin\", build_dir / \"benchmarks\", build_dir]:\n        search_paths.append(base)\n        for cfg in _config_subdirs:\n            search_paths.append(base / cfg)\n\n    for search_path in search_paths:\n        if not search_path.exists():\n            continue\n\n        for f in search_path.iterdir():\n            if not f.is_file():\n                continue\n            name = f.name\n            # Only consider executable files (on Windows, must end with .exe)\n            if platform.system() == \"Windows\" and not name.endswith(\".exe\"):\n                continue\n            if \"benchmark\" in name.lower():\n                if pattern is None or re.search(pattern, name):\n                    benchmarks.append(f)\n\n    # Remove duplicates, preferring Release over Debug\n    seen = {}\n    for bench in benchmarks:\n        key = bench.name\n        if key not in seen:\n            seen[key] = bench\n        else:\n            # Prefer Release build\n            if \"Release\" in str(bench) and \"Debug\" in str(seen[key]):\n                seen[key] = bench\n\n    return sorted(seen.values())\n\n\ndef run_benchmark(\n    benchmark_path: Path,\n    extra_args: Optional[List[str]] = None,\n    filter_pattern: Optional[str] = None,\n    env_override: Optional[Dict[str, str]] = None,\n    name_suffix: str = \"\",\n) -> Dict[str, Any]:\n    \"\"\"Run a single benchmark and return results.\"\"\"\n    args = [str(benchmark_path), \"--benchmark_format=json\"]\n    if extra_args:\n        args.extend(extra_args)\n\n    # Apply filter if provided\n    if filter_pattern:\n        args.append(f\"--benchmark_filter={filter_pattern}\")\n\n    # Special handling for nested_for_benchmark - exclude slow async cases\n    if benchmark_path.stem == \"nested_for_benchmark\" and not filter_pattern:\n        # Exclude async benchmarks (extremely slow, not competitive)\n        # Only include serial, omp, tbb, and dispenso tests\n        args.append(\"--benchmark_filter=BM_(serial|omp|tbb|dispenso)\")\n\n    result_name = benchmark_path.name + name_suffix\n\n    # Set up environment\n    env = None\n    if env_override:\n        env = os.environ.copy()\n        env.update(env_override)\n\n    print(f\"Running: {benchmark_path.name}...\")\n\n    try:\n        result = subprocess.run(\n            args,\n            capture_output=True,\n            text=True,\n            timeout=1800,  # 30 minute timeout per benchmark\n            env=env,\n        )\n\n        if result.returncode != 0:\n            error_msg = (\n                result.stderr or result.stdout or f\"exit code {result.returncode}\"\n            )\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": False,\n                \"error\": error_msg,\n            }\n\n        # Parse JSON output\n        # google benchmark outputs JSON to stdout\n        try:\n            data = json.loads(result.stdout)\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": True,\n                \"data\": data,\n            }\n        except json.JSONDecodeError:\n            # Maybe it's not a google benchmark, try to parse stdout\n            return {\n                \"name\": benchmark_path.name,\n                \"success\": True,\n                \"raw_output\": result.stdout,\n            }\n\n    except subprocess.TimeoutExpired:\n        return {\n            \"name\": benchmark_path.name,\n            \"success\": False,\n            \"error\": \"Timeout after 1800 seconds\",\n        }\n    except Exception as e:\n        return {\n            \"name\": benchmark_path.name,\n            \"success\": False,\n            \"error\": str(e),\n        }\n\n\ndef _build_extra_benchmark_args(args) -> List[str]:\n    \"\"\"Build the extra benchmark arguments list from parsed CLI args.\"\"\"\n    extra_args = []\n    if args.min_time is not None:\n        extra_args.append(f\"--benchmark_min_time={args.min_time}s\")\n    if args.repetitions is not None:\n        extra_args.append(f\"--benchmark_repetitions={args.repetitions}\")\n    return extra_args\n\n\ndef _build_windows_env_override(\n    cmake_args: Optional[List[str]],\n) -> Optional[Dict[str, str]]:\n    \"\"\"Build PATH environment override for Windows DLL discovery.\n\n    On Windows, adds bin/ dirs from CMAKE_PREFIX_PATH so vcpkg DLLs\n    (TBB, etc.) are found at benchmark runtime.\n    \"\"\"\n    if platform.system() != \"Windows\" or not cmake_args:\n        return None\n    extra_bin_dirs = []\n    for arg in cmake_args:\n        if arg.startswith(\"-DCMAKE_PREFIX_PATH=\"):\n            prefix = arg.split(\"=\", 1)[1].strip(\"\\\"'\")\n            for p in prefix.split(\";\"):\n                extra_bin_dirs.append(str(Path(p) / \"bin\"))\n    if not extra_bin_dirs:\n        return None\n    return {\n        \"PATH\": os.pathsep.join(extra_bin_dirs)\n        + os.pathsep\n        + os.environ.get(\"PATH\", \"\")\n    }\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Run dispenso benchmarks and output results as JSON\"\n    )\n    parser.add_argument(\n        \"--build\",\n        action=\"store_true\",\n        help=\"Configure and build benchmarks before running\",\n    )\n    parser.add_argument(\n        \"--source-dir\",\n        \"-s\",\n        type=Path,\n        default=DEFAULT_SOURCE_DIR,\n        help=\"Source directory (dispenso root)\",\n    )\n    parser.add_argument(\n        \"--build-dir\",\n        \"-b\",\n        type=Path,\n        default=DEFAULT_BUILD_DIR,\n        help=\"Build directory containing benchmark executables\",\n    )\n    parser.add_argument(\n        \"--output\",\n        \"-o\",\n        type=Path,\n        default=Path(\"benchmark_results.json\"),\n        help=\"Output JSON file for results\",\n    )\n    parser.add_argument(\n        \"--benchmarks\",\n        \"-B\",\n        type=str,\n        default=None,\n        help=\"Regex pattern to filter which benchmark executables to run\",\n    )\n    parser.add_argument(\n        \"--filter\",\n        \"-f\",\n        type=str,\n        default=None,\n        help=\"Filter pattern passed to --benchmark_filter for individual tests\",\n    )\n    parser.add_argument(\n        \"--min-time\",\n        type=float,\n        default=None,\n        help=\"Minimum time per benchmark in seconds (passed to --benchmark_min_time)\",\n    )\n    parser.add_argument(\n        \"--tcmalloc\",\n        type=str,\n        default=None,\n        help=\"Path to libtcmalloc.so for LD_PRELOAD tests (e.g., /usr/lib64/libtcmalloc.so.4)\",\n    )\n    parser.add_argument(\n        \"--jobs\",\n        \"-j\",\n        type=int,\n        default=os.cpu_count() or 8,\n        help=f\"Number of parallel build jobs (default: {os.cpu_count() or 8})\",\n    )\n    parser.add_argument(\n        \"--clean\",\n        action=\"store_true\",\n        help=\"Wipe the build directory before configuring (requires --build)\",\n    )\n    parser.add_argument(\n        \"--cmake-args\",\n        action=\"append\",\n        default=None,\n        metavar=\"ARG\",\n        help=\"Extra cmake argument, can be repeated \"\n        '(e.g., --cmake-args=\"-DCMAKE_CXX_COMPILER=g++-13\")',\n    )\n    parser.add_argument(\n        \"--repetitions\",\n        \"-r\",\n        type=int,\n        default=None,\n        help=\"Number of repetitions per benchmark (passed to --benchmark_repetitions). \"\n        \"Produces mean/median/stddev/cv aggregate rows in the output.\",\n    )\n    parser.add_argument(\n        \"--platform\",\n        \"-p\",\n        type=str,\n        default=None,\n        help=\"Platform identifier (e.g., 'linux-threadripper-96c'). \"\n        \"Auto-detected from machine info if not specified.\",\n    )\n\n    args = parser.parse_args()\n\n    # Gather machine info\n    print(\"Gathering machine information...\")\n    machine_info = get_machine_info()\n    print(f\"  CPU: {machine_info.get('cpu_model', 'unknown')}\")\n    print(f\"  Hardware Threads: {machine_info.get('cpu_cores', 'unknown')}\")\n    print(f\"  Memory: {machine_info.get('memory_gb', 'unknown')} GB\")\n\n    # Platform identifier (auto-detect or user-specified)\n    platform_id = args.platform or generate_platform_id(machine_info)\n    machine_info[\"platform_id\"] = platform_id\n    print(f\"  Platform: {platform_id}\")\n\n    # Build if requested\n    if args.build:\n        print()\n        if not configure_and_build(\n            source_dir=args.source_dir.resolve(),\n            build_dir=args.build_dir.resolve(),\n            jobs=args.jobs,\n            clean=args.clean,\n            benchmark_filter=args.benchmarks,\n            extra_cmake_args=args.cmake_args,\n        ):\n            sys.exit(1)\n\n    # Gather compiler info from the build directory\n    compiler_info = get_compiler_info(args.build_dir)\n    if compiler_info:\n        machine_info[\"compiler\"] = compiler_info\n        summary = compiler_info.get(\"compiler_summary\", \"unknown\")\n        print(f\"  Compiler: {summary}\")\n    print()\n\n    # Find benchmarks\n    benchmarks = find_benchmarks(args.build_dir, args.benchmarks)\n    if not benchmarks:\n        print(f\"No benchmarks found in {args.build_dir}\")\n        print(\"Make sure you've built with -DDISPENSO_BUILD_BENCHMARKS=ON\")\n        sys.exit(1)\n\n    print(f\"Found {len(benchmarks)} benchmark(s):\")\n    for b in benchmarks:\n        print(f\"  - {b.name}\")\n    print()\n\n    # Run benchmarks\n    extra_args = _build_extra_benchmark_args(args)\n    env_override = _build_windows_env_override(args.cmake_args)\n\n    results = []\n    for benchmark in benchmarks:\n        result = run_benchmark(\n            benchmark,\n            extra_args if extra_args else None,\n            args.filter,\n            env_override=env_override,\n        )\n        results.append(result)\n        if result[\"success\"]:\n            print(f\"  OK {benchmark.name}\")\n        else:\n            print(\n                f\"  FAIL {benchmark.name}: {result.get('error', 'unknown error')[:200]}\"\n            )\n\n    # Save results\n    args.output.parent.mkdir(parents=True, exist_ok=True)\n\n    output_data = {\n        \"machine_info\": machine_info,\n        \"results\": results,\n    }\n\n    with open(args.output, \"w\") as f:\n        json.dump(output_data, f, indent=2, default=str)\n    print(f\"\\nSaved results to: {args.output}\")\n\n    # Print summary\n    successful = sum(1 for r in results if r.get(\"success\"))\n    print(f\"\\nSummary: {successful}/{len(results)} benchmarks succeeded\")\n\n    if successful < len(results):\n        sys.exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/update_benchmarks.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"\nOne-stop-shop for updating benchmarks and documentation.\n\nThis script orchestrates the full benchmark workflow:\n1. Configures and builds dispenso with benchmarks enabled\n2. Runs benchmarks via run_benchmarks.py\n3. Generates charts via generate_charts.py\n4. Copies charts to docs/benchmarks/ with README-compatible names\n5. Updates benchmark_results.md with detailed results\n\nMulti-platform compose mode:\n  Accepts pre-generated JSON results from multiple platforms and generates\n  per-platform subdirectories with a unified landing page.\n\nUsage:\n    # Full run (build + run + charts) for current platform\n    python update_benchmarks.py --platform linux-threadripper\n\n    # Use existing build directory\n    python update_benchmarks.py -b /path/to/build --skip-build --platform linux-threadripper\n\n    # Run specific benchmarks only\n    python update_benchmarks.py -B \"concurrent_vector|pipeline\"\n\n    # Compose mode: generate docs from multiple platform results\n    python update_benchmarks.py --compose \\\\\n        linux-threadripper:results/linux.json \\\\\n        macos-m2:results/macos.json \\\\\n        windows-zen4:results/windows.json\n\nRequirements:\n    pip install matplotlib pandas\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport shutil\nimport subprocess\nimport sys\nfrom pathlib import Path\n\nSCRIPT_DIR = Path(__file__).parent\nSOURCE_DIR = SCRIPT_DIR.parent\nDOCS_DIR = SOURCE_DIR / \"docs\" / \"benchmarks\"\nDEFAULT_BUILD_DIR = Path(\"/tmp/dispenso-benchmark-build\")\n\n# Chart name mapping: generated name -> README expected name\n# The README.md references specific filenames that we need to maintain\nREADME_CHART_MAPPING = {\n    # future benchmark generates future_zoomed_chart.png, README expects par_tree_build.png\n    \"future_zoomed_chart.png\": \"par_tree_build.png\",\n    # simple_for 1M zoomed is used for README parallel for section (shows competitive cases)\n    \"simple_for_1000000_zoomed_chart.png\": \"simple_for.png\",\n    # pipeline chart\n    \"pipeline_chart.png\": \"pipeline.png\",\n    # concurrent_vector parallel chart maps to the README name\n    \"concurrent_vector_parallel_chart.png\": \"concurrent_vector.png\",\n    # nested_for charts map to README expected names\n    \"nested_for_10_chart.png\": \"nested_for_small.png\",\n    \"nested_for_500_chart.png\": \"nested_for_medium.png\",\n    \"nested_for_3000_chart.png\": \"nested_for_large.png\",\n}\n\n\ndef run_command(cmd: list, description: str, cwd: Path = None) -> bool:\n    \"\"\"Run a command and return success status.\"\"\"\n    print(f\"  Running: {' '.join(str(c) for c in cmd)}\")\n    result = subprocess.run(cmd, cwd=cwd)\n    if result.returncode != 0:\n        print(f\"  Error: {description} failed with code {result.returncode}\")\n        return False\n    return True\n\n\ndef configure_build(build_dir: Path, source_dir: Path, jobs: int) -> bool:\n    \"\"\"Configure cmake build with benchmarks enabled.\"\"\"\n    build_dir.mkdir(parents=True, exist_ok=True)\n\n    cmake_cmd = [\n        \"cmake\",\n        str(source_dir),\n        \"-DDISPENSO_BUILD_BENCHMARKS=ON\",\n        \"-DCMAKE_BUILD_TYPE=Release\",\n        \"-DCMAKE_CXX_STANDARD=20\",  # C++20 for folly and taskflow 3.x support\n        \"-DBENCHMARK_WITHOUT_FOLLY=OFF\",\n    ]\n\n    print(\"  CMake configuration:\")\n    print(\"    - C++20 (for folly and taskflow support)\")\n    print(\"    - Release mode (-O3)\")\n    print(\"    - Folly enabled\")\n    print()\n\n    return run_command(cmake_cmd, \"CMake configure\", cwd=build_dir)\n\n\ndef build_benchmarks(build_dir: Path, jobs: int) -> bool:\n    \"\"\"Build the benchmarks.\"\"\"\n    make_cmd = [\"make\", f\"-j{jobs}\"]\n    return run_command(make_cmd, \"Build\", cwd=build_dir)\n\n\ndef copy_all_charts(charts_dir: Path, docs_dir: Path) -> int:\n    \"\"\"Copy all charts and markdown files from charts_dir to docs_dir.\n\n    Returns count of files copied.\n    \"\"\"\n    docs_dir.mkdir(parents=True, exist_ok=True)\n    count = 0\n\n    # Copy all PNG files\n    for src_path in charts_dir.glob(\"*.png\"):\n        dst_path = docs_dir / src_path.name\n        shutil.copy2(src_path, dst_path)\n        count += 1\n\n    # Copy all markdown detail files\n    for src_path in charts_dir.glob(\"*_details.md\"):\n        dst_path = docs_dir / src_path.name\n        shutil.copy2(src_path, dst_path)\n        count += 1\n\n    # Copy benchmark report as benchmark_results.md\n    report_src = charts_dir / \"benchmark_report.md\"\n    if report_src.exists():\n        shutil.copy2(report_src, docs_dir / \"benchmark_results.md\")\n        count += 1\n\n    return count\n\n\ndef copy_readme_charts(charts_dir: Path, docs_dir: Path) -> list:\n    \"\"\"Copy charts with README-compatible names.\n\n    Returns list of (src, dst) pairs that were copied.\n    \"\"\"\n    copied = []\n\n    for src_name, dst_name in README_CHART_MAPPING.items():\n        src_path = charts_dir / src_name\n        dst_path = docs_dir / dst_name\n        if src_path.exists():\n            shutil.copy2(src_path, dst_path)\n            copied.append((src_name, dst_name))\n            print(f\"  Copied: {src_name} -> {dst_name}\")\n        else:\n            print(f\"  Warning: Source chart not found: {src_name}\")\n\n    return copied\n\n\ndef generate_landing_page(docs_dir: Path, platforms: list) -> Path:\n    \"\"\"Generate a landing page linking to all per-platform benchmark results.\n\n    Args:\n        docs_dir: The docs/benchmarks/ directory.\n        platforms: List of dicts with keys: name, cpu, threads, memory, timestamp.\n\n    Returns:\n        Path to the generated landing page.\n    \"\"\"\n    landing_path = docs_dir / \"benchmark_results.md\"\n\n    with open(landing_path, \"w\") as f:\n        f.write(\"# Dispenso Benchmark Results\\n\\n\")\n        f.write(\"Benchmark results across multiple platforms.\\n\\n\")\n        f.write(\"## Platforms\\n\\n\")\n        f.write(\"| Platform | CPU | Threads | Memory | Date |\\n\")\n        f.write(\"|----------|-----|---------|--------|------|\\n\")\n\n        for p in platforms:\n            report_link = f\"[{p['name']}]({p['name']}/benchmark_results.md)\"\n            f.write(\n                f\"| {report_link} | {p.get('cpu', '?')} | \"\n                f\"{p.get('threads', '?')} | {p.get('memory', '?')} GB | \"\n                f\"{p.get('timestamp', '?')} |\\n\"\n            )\n\n        f.write(\"\\n---\\n\\n\")\n        f.write(\"Each platform directory contains:\\n\")\n        f.write(\"- `benchmark_results.md` — Full benchmark report with charts\\n\")\n        f.write(\"- `*_details.md` — Per-suite detailed result tables\\n\")\n        f.write(\"- `*.png` — Individual chart images\\n\")\n\n    print(f\"Generated landing page: {landing_path}\")\n    return landing_path\n\n\ndef compose_platforms(platform_specs: list, docs_dir: Path) -> bool:\n    \"\"\"Compose multi-platform benchmark results.\n\n    For each platform, runs generate_charts.py with --platform, then copies\n    results to docs/benchmarks/<platform>/. Finally generates a landing page.\n\n    Args:\n        platform_specs: List of \"platform_name:json_path\" strings.\n        docs_dir: Target docs/benchmarks/ directory.\n\n    Returns:\n        True on success.\n    \"\"\"\n    platforms = []\n\n    for spec in platform_specs:\n        if \":\" not in spec:\n            print(\n                f\"Error: Invalid platform spec '{spec}'. Expected 'name:path/to/results.json'\"\n            )\n            return False\n\n        name, json_path_str = spec.split(\":\", 1)\n        json_path = Path(json_path_str).resolve()\n\n        if not json_path.exists():\n            print(f\"Error: Results file not found: {json_path}\")\n            return False\n\n        # Read machine info from JSON\n        with open(json_path) as f:\n            data = json.load(f)\n        machine_info = data.get(\"machine_info\", {})\n\n        platforms.append(\n            {\n                \"name\": name,\n                \"json_path\": json_path,\n                \"cpu\": machine_info.get(\"cpu_model\", \"unknown\"),\n                \"threads\": machine_info.get(\"cpu_cores\", \"?\"),\n                \"memory\": machine_info.get(\"memory_gb\", \"?\"),\n                \"timestamp\": machine_info.get(\"timestamp\", \"unknown\"),\n            }\n        )\n\n    print(f\"Composing results for {len(platforms)} platform(s):\")\n    for p in platforms:\n        print(f\"  {p['name']}: {p['json_path']} ({p['cpu']}, {p['threads']} threads)\")\n    print()\n\n    # Generate charts for each platform\n    for p in platforms:\n        print(f\"Generating charts for {p['name']}...\")\n        print(\"-\" * 40)\n\n        charts_dir = docs_dir / p[\"name\"]\n        chart_cmd = [\n            sys.executable,\n            str(SCRIPT_DIR / \"generate_charts.py\"),\n            \"-i\",\n            str(p[\"json_path\"]),\n            \"-o\",\n            str(charts_dir),\n        ]\n\n        result = subprocess.run(chart_cmd)\n        if result.returncode != 0:\n            print(f\"Error: Chart generation failed for {p['name']}\")\n            return False\n        print()\n\n    # Copy README-compatible charts from the first platform (primary)\n    primary = platforms[0]\n    primary_charts = docs_dir / primary[\"name\"]\n    print(f\"Copying README charts from primary platform ({primary['name']})...\")\n    print(\"-\" * 40)\n    copied = copy_readme_charts(primary_charts, docs_dir)\n    print(f\"  Created {len(copied)} README-compatible chart names\")\n    print()\n\n    # Generate landing page\n    print(\"Generating landing page...\")\n    print(\"-\" * 40)\n    generate_landing_page(docs_dir, platforms)\n    print()\n\n    return True\n\n\ndef _step_build(build_dir: Path, source_dir: Path, jobs: int, skip: bool) -> bool:\n    \"\"\"Handle the build steps (configure + build). Returns True on success.\"\"\"\n    if skip:\n        print(\"Step 1-2: Skipping build (--skip-build)\")\n        if not (build_dir / \"bin\").exists():\n            print(f\"Error: Build directory does not contain bin/: {build_dir}\")\n            return False\n        print()\n        return True\n\n    print(\"Step 1: Configuring cmake...\")\n    print(\"-\" * 40)\n    if not configure_build(build_dir, source_dir, jobs):\n        return False\n    print()\n\n    print(\"Step 2: Building benchmarks...\")\n    print(\"-\" * 40)\n    if not build_benchmarks(build_dir, jobs):\n        return False\n    print()\n    return True\n\n\ndef _step_run(\n    json_path: Path,\n    build_dir: Path,\n    benchmarks: str,\n    min_time: float,\n    skip: bool,\n    step_num: int,\n) -> bool:\n    \"\"\"Handle the benchmark run step. Returns True on success.\"\"\"\n    output_dir = json_path.parent\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    if skip:\n        print(f\"Step {step_num}: Skipping benchmark run (--skip-run)\")\n        if not json_path.exists():\n            print(f\"Error: Results file not found: {json_path}\")\n            return False\n        print()\n        return True\n\n    print(f\"Step {step_num}: Running benchmarks...\")\n    print(\"-\" * 40)\n\n    run_cmd = [\n        sys.executable,\n        str(SCRIPT_DIR / \"run_benchmarks.py\"),\n        \"-b\",\n        str(build_dir),\n        \"-o\",\n        str(json_path),\n    ]\n    if benchmarks:\n        run_cmd.extend([\"-B\", benchmarks])\n    if min_time:\n        run_cmd.extend([\"--min-time\", str(min_time)])\n\n    result = subprocess.run(run_cmd)\n    if result.returncode != 0:\n        print(\"Error: Benchmark run failed\")\n        return False\n    print()\n    return True\n\n\ndef _step_generate_charts(\n    json_path: Path,\n    charts_dir: Path,\n    platform_id: str,\n    skip: bool,\n    step_num: int,\n) -> bool:\n    \"\"\"Handle the chart generation step. Returns True on success.\"\"\"\n    if skip:\n        print(f\"Step {step_num}: Skipping chart generation (--skip-charts)\")\n        if not charts_dir.exists():\n            print(f\"Error: Charts directory not found: {charts_dir}\")\n            return False\n        print()\n        return True\n\n    print(f\"Step {step_num}: Generating charts...\")\n    print(\"-\" * 40)\n\n    chart_cmd = [\n        sys.executable,\n        str(SCRIPT_DIR / \"generate_charts.py\"),\n        \"-i\",\n        str(json_path),\n        \"-o\",\n        str(charts_dir),\n    ]\n    if platform_id:\n        chart_cmd.extend([\"-p\", platform_id])\n\n    result = subprocess.run(chart_cmd)\n    if result.returncode != 0:\n        print(\"Error: Chart generation failed\")\n        return False\n    print()\n    return True\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description=\"Update dispenso benchmarks and documentation\"\n    )\n    parser.add_argument(\n        \"--build-dir\",\n        \"-b\",\n        type=Path,\n        default=DEFAULT_BUILD_DIR,\n        help=f\"Build directory (default: {DEFAULT_BUILD_DIR})\",\n    )\n    parser.add_argument(\n        \"--source-dir\",\n        \"-s\",\n        type=Path,\n        default=SOURCE_DIR,\n        help=f\"Dispenso source directory (default: {SOURCE_DIR})\",\n    )\n    parser.add_argument(\n        \"--output-dir\",\n        \"-o\",\n        type=Path,\n        default=None,\n        help=\"Temporary output directory for results (default: build-dir/benchmark_output)\",\n    )\n    parser.add_argument(\n        \"--jobs\",\n        \"-j\",\n        type=int,\n        default=os.cpu_count() or 8,\n        help=f\"Number of parallel build jobs (default: {os.cpu_count() or 8})\",\n    )\n    parser.add_argument(\n        \"--clean\",\n        action=\"store_true\",\n        help=\"Clean build directory before building\",\n    )\n    parser.add_argument(\n        \"--skip-build\",\n        action=\"store_true\",\n        help=\"Skip cmake configure and build (use existing build)\",\n    )\n    parser.add_argument(\n        \"--skip-run\",\n        action=\"store_true\",\n        help=\"Skip running benchmarks (use existing results.json)\",\n    )\n    parser.add_argument(\n        \"--skip-charts\",\n        action=\"store_true\",\n        help=\"Skip chart generation (use existing charts)\",\n    )\n    parser.add_argument(\n        \"--benchmarks\",\n        \"-B\",\n        type=str,\n        default=None,\n        help=\"Regex pattern to filter which benchmark executables to run\",\n    )\n    parser.add_argument(\n        \"--min-time\",\n        type=float,\n        default=None,\n        help=\"Minimum time per benchmark in seconds\",\n    )\n    parser.add_argument(\n        \"--platform\",\n        \"-p\",\n        type=str,\n        default=None,\n        help=\"Platform identifier (e.g., 'linux-threadripper'). \"\n        \"Charts go into docs/benchmarks/<platform>/ subdirectory.\",\n    )\n    parser.add_argument(\n        \"--compose\",\n        nargs=\"+\",\n        metavar=\"PLATFORM:JSON_PATH\",\n        help=\"Compose mode: generate docs from multiple platform results. \"\n        \"Each argument is 'platform-name:/path/to/results.json'. \"\n        \"Example: --compose linux-threadripper:linux.json macos-m2:macos.json\",\n    )\n\n    args = parser.parse_args()\n\n    # Compose mode: just generate per-platform charts + landing page\n    if args.compose:\n        print(\"=\" * 60)\n        print(\"Dispenso Multi-Platform Benchmark Compose\")\n        print(\"=\" * 60)\n        print(f\"Docs directory: {DOCS_DIR}\")\n        print()\n\n        if not compose_platforms(args.compose, DOCS_DIR):\n            sys.exit(1)\n\n        print(\"=\" * 60)\n        print(\"Compose Complete!\")\n        print(\"=\" * 60)\n        print()\n        print(\"Next steps:\")\n        print(\"  1. Review the charts in docs/benchmarks/\")\n        print(\"  2. Verify README.md displays correctly\")\n        print(\"  3. Run: sl status\")\n        print(\"  4. Commit the updated charts\")\n        print()\n        return\n\n    # Normal mode: build + run + generate charts for a single platform\n    build_dir = args.build_dir.resolve()\n    source_dir = args.source_dir.resolve()\n    output_dir = args.output_dir or (build_dir / \"benchmark_output\")\n    json_path = output_dir / \"benchmark_results.json\"\n    charts_dir = output_dir / \"charts\"\n\n    # When platform is set, docs go into a subdirectory\n    docs_dir = DOCS_DIR\n    if args.platform:\n        docs_dir = DOCS_DIR / args.platform\n\n    print(\"=\" * 60)\n    print(\"Dispenso Benchmark Update\")\n    print(\"=\" * 60)\n    print(f\"Source directory: {source_dir}\")\n    print(f\"Build directory:  {build_dir}\")\n    print(f\"Output directory: {output_dir}\")\n    print(f\"Docs directory:   {docs_dir}\")\n    if args.platform:\n        print(f\"Platform:         {args.platform}\")\n    print(f\"Parallel jobs:    {args.jobs}\")\n    print()\n\n    # Step 0: Clean if requested\n    if args.clean and build_dir.exists():\n        print(\"Step 0: Cleaning build directory...\")\n        print(\"-\" * 40)\n        shutil.rmtree(build_dir)\n        print(f\"  Removed: {build_dir}\")\n        print()\n\n    # Steps 1-2: Configure and build\n    if not _step_build(build_dir, source_dir, args.jobs, args.skip_build):\n        sys.exit(1)\n    step_offset = 0 if args.skip_build else 2\n\n    # Step 3: Run benchmarks\n    if not _step_run(\n        json_path,\n        build_dir,\n        args.benchmarks,\n        args.min_time,\n        args.skip_run,\n        3 + step_offset,\n    ):\n        sys.exit(1)\n\n    # Step 4: Generate charts\n    if not _step_generate_charts(\n        json_path,\n        charts_dir,\n        args.platform,\n        args.skip_charts,\n        4 + step_offset,\n    ):\n        sys.exit(1)\n\n    # When --platform is used, charts are already in a platform subdir\n    src_charts_dir = charts_dir\n    if args.platform:\n        src_charts_dir = charts_dir / args.platform\n\n    # Step 5: Copy all charts to docs/benchmarks[/<platform>]/\n    print(f\"Step {5 + step_offset}: Copying all charts to {docs_dir}/...\")\n    print(\"-\" * 40)\n\n    file_count = copy_all_charts(src_charts_dir, docs_dir)\n    print(f\"  Copied {file_count} files (charts + markdown)\")\n    print()\n\n    # Step 6: Copy README-specific charts with mapping\n    print(f\"Step {6 + step_offset}: Copying README charts with mapped names...\")\n    print(\"-\" * 40)\n\n    # README charts go to the top-level docs/benchmarks/ regardless of platform\n    copied = copy_readme_charts(src_charts_dir, DOCS_DIR)\n    print(f\"  Created {len(copied)} README-compatible chart names\")\n    print()\n\n    # Summary\n    print(\"=\" * 60)\n    print(\"Update Complete!\")\n    print(\"=\" * 60)\n    print()\n    print(f\"Charts copied to {docs_dir}/:\")\n    for src, dst in copied:\n        print(f\"  {dst}\")\n    print()\n    print(\"Next steps:\")\n    print(\"  1. Review the charts in docs/benchmarks/\")\n    print(\"  2. Verify README.md displays correctly\")\n    print(\"  3. Run: sl status\")\n    print(\"  4. Commit the updated charts\")\n    print()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/update_package_managers.py",
    "content": "#!/usr/bin/env python3\n# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\"\"\"Update dispenso across package manager repositories for a new release.\n\nDownloads the release tarball, computes hashes, updates version/hash references\nin each package manager's repo, commits, tests locally, pushes to the user's\nfork, and creates PRs.\n\nRecommended usage (interactive guided flow):\n    python3 update_package_managers.py --version 1.5.1 --guided\n\nThe guided flow walks through every step: updating each manager, running tests,\ninspecting diffs, pushing, closing superseded PRs, creating new PRs, and\nguiding through any remaining manual steps like CLA signing.\n\nAdvanced usage (individual flags):\n    python3 update_package_managers.py --version 1.5.1 --managers conan,vcpkg\n    python3 update_package_managers.py --version 1.5.1 --dry-run\n    python3 update_package_managers.py --version 1.5.1 --skip-test\n    python3 update_package_managers.py --version 1.5.1 --skip-push\n    python3 update_package_managers.py --version 1.5.1 --create-prs\n\"\"\"\n\nimport argparse\nimport hashlib\nimport json\nimport os\nimport platform\nimport re\nimport shutil\nimport subprocess\nimport sys\nimport tarfile\nimport tempfile\nimport urllib.request\n\nGITHUB_REPO = \"facebookincubator/dispenso\"\nMANAGERS = [\"conan\", \"vcpkg\", \"homebrew\", \"macports\"]\n\n# Upstream repos and default branch names for each manager\nUPSTREAM_REPOS = {\n    \"conan\": \"conan-io/conan-center-index\",\n    \"vcpkg\": \"microsoft/vcpkg\",\n    \"homebrew\": \"Homebrew/homebrew-core\",\n    \"macports\": \"macports/macports-ports\",\n}\n\nREPO_DIRS = {\n    \"conan\": \"conan-center-index\",\n    \"vcpkg\": \"vcpkg\",\n    \"homebrew\": \"homebrew-core\",\n    \"macports\": \"macports-ports\",\n}\n\nBRANCH_NAMES = {\n    \"conan\": \"package/dispenso\",\n    \"vcpkg\": \"add-dispenso\",\n    # homebrew and macports use version-specific branches, set dynamically\n}\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description=\"Update dispenso across package manager repositories.\"\n    )\n    parser.add_argument(\"--version\", required=True, help=\"Release version, e.g. 1.5.0\")\n    parser.add_argument(\n        \"--managers\",\n        default=\",\".join(MANAGERS),\n        help=f\"Comma-separated list of managers to update (default: {','.join(MANAGERS)})\",\n    )\n    parser.add_argument(\n        \"--dry-run\",\n        action=\"store_true\",\n        help=\"Print what would be done without modifying files or pushing\",\n    )\n    parser.add_argument(\n        \"--skip-test\",\n        action=\"store_true\",\n        help=\"Skip local verification tests after committing\",\n    )\n    parser.add_argument(\n        \"--skip-push\",\n        action=\"store_true\",\n        help=\"Update files, commit, and test but don't push to fork\",\n    )\n    parser.add_argument(\n        \"--repos-dir\",\n        default=os.path.expanduser(\"~/repos\"),\n        help=\"Base directory containing cloned repos (default: ~/repos)\",\n    )\n    parser.add_argument(\n        \"--github-user\",\n        default=\"graphicsMan\",\n        help=\"GitHub fork username (default: graphicsMan)\",\n    )\n    parser.add_argument(\n        \"--create-prs\",\n        action=\"store_true\",\n        help=\"Create PRs on GitHub after pushing (uses gh CLI)\",\n    )\n    parser.add_argument(\n        \"--guided\",\n        action=\"store_true\",\n        help=\"Interactive guided flow: walks through every step, prompts \"\n        \"before each action, creates PRs at the end\",\n    )\n    args = parser.parse_args()\n    if not re.match(r\"^\\d+\\.\\d+\\.\\d+$\", args.version):\n        parser.error(\n            f\"Invalid version format: {args.version!r}. Expected semver like 1.5.1\"\n        )\n    args.managers = [m.strip() for m in args.managers.split(\",\")]\n    for m in args.managers:\n        if m not in MANAGERS:\n            parser.error(f\"Unknown manager: {m}. Choose from: {', '.join(MANAGERS)}\")\n    return args\n\n\ndef download_and_hash(version):\n    \"\"\"Download the release tarball and compute sha256, sha512, rmd160, and size.\"\"\"\n    url = f\"https://github.com/{GITHUB_REPO}/archive/refs/tags/v{version}.tar.gz\"\n    print(f\"Downloading {url} ...\")\n\n    tarball_path = os.path.join(tempfile.gettempdir(), f\"dispenso-v{version}.tar.gz\")\n\n    # Download (or reuse if already present and non-empty)\n    if os.path.exists(tarball_path) and os.path.getsize(tarball_path) > 0:\n        print(f\"  Using cached tarball: {tarball_path}\")\n    else:\n        urllib.request.urlretrieve(url, tarball_path)\n        print(f\"  Saved to {tarball_path}\")\n\n    data = open(tarball_path, \"rb\").read()\n    size = len(data)\n\n    sha256 = hashlib.sha256(data).hexdigest()\n    sha512 = hashlib.sha512(data).hexdigest()\n\n    # RIPEMD-160: try hashlib first, fall back to openssl subprocess\n    try:\n        rmd160 = hashlib.new(\"ripemd160\", data).hexdigest()\n    except ValueError:\n        # hashlib doesn't support rmd160 on this system, try openssl\n        try:\n            result = subprocess.run(\n                [\"openssl\", \"dgst\", \"-rmd160\", tarball_path],\n                capture_output=True,\n                text=True,\n                check=True,\n            )\n            # Output format: \"RIPEMD-160(file)= <hex>\"\n            rmd160 = result.stdout.strip().split(\"= \")[-1]\n        except (FileNotFoundError, subprocess.CalledProcessError):\n            rmd160 = None\n            print(\"  WARNING: Could not compute RIPEMD-160 (needed for MacPorts)\")\n\n    hashes = {\n        \"sha256\": sha256,\n        \"sha512\": sha512,\n        \"rmd160\": rmd160,\n        \"size\": size,\n        \"url\": url,\n    }\n\n    print(f\"  SHA256:  {sha256}\")\n    print(f\"  SHA512:  {sha512}\")\n    print(f\"  RMD160:  {rmd160}\")\n    print(f\"  Size:    {size}\")\n    print()\n\n    return tarball_path, hashes\n\n\ndef run(cmd, cwd=None, check=True, dry_run=False, capture=False, env=None):\n    \"\"\"Run a shell command, printing it first. Respects dry_run.\"\"\"\n    if isinstance(cmd, str):\n        display = cmd\n    else:\n        display = \" \".join(cmd)\n\n    prefix = \"[DRY RUN] \" if dry_run else \"\"\n    print(f\"  {prefix}$ {display}\")\n\n    if dry_run:\n        return subprocess.CompletedProcess(cmd, 0, stdout=\"\", stderr=\"\")\n\n    kwargs = {\"cwd\": cwd, \"check\": check}\n    if capture:\n        kwargs[\"capture_output\"] = True\n        kwargs[\"text\"] = True\n    if env is not None:\n        kwargs[\"env\"] = env\n\n    return subprocess.run(cmd, **kwargs)\n\n\ndef ensure_repo(repos_dir, manager, github_user, dry_run):\n    \"\"\"Clone if missing, add fork remote, fetch upstream.\"\"\"\n    upstream = UPSTREAM_REPOS[manager]\n    repo_name = REPO_DIRS[manager]\n    repo_dir = os.path.join(repos_dir, repo_name)\n\n    if not os.path.isdir(repo_dir):\n        print(f\"  Cloning {upstream} ...\")\n        run(\n            [\"git\", \"clone\", f\"https://github.com/{upstream}.git\", repo_dir],\n            dry_run=dry_run,\n        )\n    else:\n        print(f\"  Repo already exists: {repo_dir}\")\n\n    if dry_run:\n        return repo_dir\n\n    # Ensure upstream remote points to the right place\n    result = subprocess.run(\n        [\"git\", \"remote\", \"get-url\", \"origin\"],\n        cwd=repo_dir,\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        current_origin = result.stdout.strip()\n        # Normalize: also accept SSH format\n        if upstream not in current_origin:\n            print(f\"  WARNING: origin points to {current_origin}, expected {upstream}\")\n\n    # Ensure fork remote exists\n    result = subprocess.run(\n        [\"git\", \"remote\", \"get-url\", \"fork\"],\n        cwd=repo_dir,\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode != 0:\n        print(f\"  Adding fork remote for {github_user}/{repo_name} ...\")\n        # Ensure the fork exists on GitHub\n        run(\n            [\"gh\", \"repo\", \"fork\", upstream, \"--clone=false\"],\n            cwd=repo_dir,\n            check=False,\n        )\n        run(\n            [\n                \"git\",\n                \"remote\",\n                \"add\",\n                \"fork\",\n                f\"git@github.com:{github_user}/{repo_name}.git\",\n            ],\n            cwd=repo_dir,\n        )\n    else:\n        print(\"  Fork remote already exists\")\n\n    # Fetch upstream\n    print(\"  Fetching origin ...\")\n    run([\"git\", \"fetch\", \"origin\"], cwd=repo_dir)\n\n    return repo_dir\n\n\ndef checkout_branch(repo_dir, branch, dry_run):\n    \"\"\"Determine the default branch, update it, and create/checkout the working branch.\"\"\"\n    if dry_run:\n        print(f\"  [DRY RUN] Would checkout branch: {branch}\")\n        return\n\n    # Determine default branch (main or master)\n    result = subprocess.run(\n        [\"git\", \"symbolic-ref\", \"refs/remotes/origin/HEAD\"],\n        cwd=repo_dir,\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        default_branch = result.stdout.strip().replace(\"refs/remotes/origin/\", \"\")\n    else:\n        # Try common names\n        for candidate in [\"main\", \"master\"]:\n            r = subprocess.run(\n                [\"git\", \"show-ref\", \"--verify\", f\"refs/remotes/origin/{candidate}\"],\n                cwd=repo_dir,\n                capture_output=True,\n            )\n            if r.returncode == 0:\n                default_branch = candidate\n                break\n        else:\n            default_branch = \"main\"\n\n    # Abort any in-progress rebase (e.g. from a previous failed run)\n    rebase_merge = os.path.join(repo_dir, \".git\", \"rebase-merge\")\n    rebase_apply = os.path.join(repo_dir, \".git\", \"rebase-apply\")\n    if os.path.isdir(rebase_merge) or os.path.isdir(rebase_apply):\n        print(\"  Aborting in-progress rebase from previous run ...\")\n        run([\"git\", \"rebase\", \"--abort\"], cwd=repo_dir, check=False)\n\n    # Stash any dirty changes so we can switch branches\n    result = subprocess.run(\n        [\"git\", \"status\", \"--porcelain\"],\n        cwd=repo_dir,\n        capture_output=True,\n        text=True,\n    )\n    stashed = False\n    if result.stdout.strip():\n        print(\"  Stashing dirty changes ...\")\n        run([\"git\", \"stash\", \"--include-untracked\"], cwd=repo_dir)\n        stashed = True\n\n    # Checkout and update default branch\n    run([\"git\", \"checkout\", default_branch], cwd=repo_dir)\n    run([\"git\", \"pull\", \"origin\", default_branch], cwd=repo_dir)\n\n    # Create or reset working branch to start fresh from default branch.\n    # We reset instead of rebase because the script overwrites all port files\n    # and commit_and_push() squashes into one commit anyway.  Rebasing can\n    # conflict when a previous version's changes were already merged.\n    result = subprocess.run(\n        [\"git\", \"show-ref\", \"--verify\", f\"refs/heads/{branch}\"],\n        cwd=repo_dir,\n        capture_output=True,\n    )\n    if result.returncode == 0:\n        print(f\"  Branch {branch} already exists, resetting to {default_branch} ...\")\n        run([\"git\", \"checkout\", branch], cwd=repo_dir)\n        run([\"git\", \"reset\", \"--hard\", default_branch], cwd=repo_dir)\n    else:\n        print(f\"  Creating branch {branch} from {default_branch} ...\")\n        run([\"git\", \"checkout\", \"-b\", branch], cwd=repo_dir)\n\n    # Restore stashed changes if any\n    if stashed:\n        print(\"  Restoring stashed changes ...\")\n        run([\"git\", \"stash\", \"pop\"], cwd=repo_dir, check=False)\n\n\ndef commit_and_push(repo_dir, branch, message, github_user, dry_run, skip_push):\n    \"\"\"Stage all changes, squash into a single commit, push to fork.\n\n    If the branch already has commits beyond the upstream base, soft-reset to the\n    base and re-commit everything as a single commit. This ensures the branch always\n    has exactly one clean commit regardless of how many iterations have been made.\n    \"\"\"\n    if dry_run:\n        run([\"git\", \"add\", \"-A\"], cwd=repo_dir, dry_run=True)\n        run([\"git\", \"commit\", \"-m\", message], cwd=repo_dir, dry_run=True)\n        if not skip_push:\n            run(\n                [\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"],\n                cwd=repo_dir,\n                dry_run=True,\n            )\n        return True\n\n    # Stage everything\n    run([\"git\", \"add\", \"-A\"], cwd=repo_dir)\n\n    # Find the merge base with the upstream default branch\n    merge_base = None\n    for candidate in [\"origin/main\", \"origin/master\"]:\n        result = subprocess.run(\n            [\"git\", \"merge-base\", candidate, \"HEAD\"],\n            cwd=repo_dir,\n            capture_output=True,\n            text=True,\n        )\n        if result.returncode == 0:\n            merge_base = result.stdout.strip()\n            break\n\n    if merge_base:\n        # Check if there are any differences from the merge base\n        result = subprocess.run(\n            [\"git\", \"diff\", \"--cached\", merge_base, \"--quiet\"],\n            cwd=repo_dir,\n        )\n        if result.returncode == 0:\n            # Also check uncommitted staged changes\n            result = subprocess.run(\n                [\"git\", \"diff\", \"--cached\", \"--quiet\"],\n                cwd=repo_dir,\n            )\n            if result.returncode == 0:\n                print(\n                    \"  WARNING: No changes to commit — upstream already\"\n                    \" has this version. Skipping.\"\n                )\n                return False\n\n        # Soft-reset to merge base and recommit as single commit.\n        # Re-add after reset so the index reflects all working-tree changes\n        # relative to the new HEAD (merge_base), not the old HEAD.\n        print(\"  Squashing into single commit ...\")\n        run([\"git\", \"reset\", \"--soft\", merge_base], cwd=repo_dir)\n        run([\"git\", \"add\", \"-A\"], cwd=repo_dir)\n        run([\"git\", \"commit\", \"-m\", message], cwd=repo_dir)\n    else:\n        # Fallback: just commit normally if we can't find a merge base\n        result = subprocess.run(\n            [\"git\", \"diff\", \"--cached\", \"--quiet\"],\n            cwd=repo_dir,\n        )\n        if result.returncode == 0:\n            print(\"  No staged changes to commit\")\n        else:\n            run([\"git\", \"commit\", \"-m\", message], cwd=repo_dir)\n\n    if not skip_push:\n        run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n\n    return True\n\n\n# ---------------------------------------------------------------------------\n# Per-manager test functions\n# ---------------------------------------------------------------------------\n\n\ndef test_conan(repo_dir, version):\n    \"\"\"Test conan recipe with conan create.\"\"\"\n    conan_bin = shutil.which(\"conan\")\n    if not conan_bin:\n        print(\"  WARNING: conan not found, skipping test\")\n        return False\n\n    print(\"  Running conan create ...\")\n    result = run(\n        [conan_bin, \"create\", \"recipes/dispenso/all\", f\"--version={version}\"],\n        cwd=repo_dir,\n        check=False,\n    )\n    if result.returncode != 0:\n        print(\"  FAIL: conan create failed\")\n        return False\n\n    print(\"  PASS: conan create succeeded\")\n    return True\n\n\ndef test_vcpkg(repo_dir, version):\n    \"\"\"Test vcpkg port with vcpkg install.\"\"\"\n    vcpkg_bin = shutil.which(\"vcpkg\")\n    if not vcpkg_bin:\n        print(\"  WARNING: vcpkg not found, skipping test\")\n        return False\n\n    # Detect default triplet so we remove/install for the right platform\n    if sys.platform == \"darwin\":\n        machine = platform.machine()  # arm64 or x86_64\n        default_triplet = \"arm64-osx\" if machine == \"arm64\" else \"x64-osx\"\n    elif sys.platform == \"win32\":\n        default_triplet = \"x64-windows\"\n    else:\n        default_triplet = \"x64-linux\"\n\n    # Remove existing install to force rebuild\n    print(f\"  Removing existing vcpkg install (if any) [{default_triplet}] ...\")\n    run(\n        [vcpkg_bin, \"remove\", f\"dispenso:{default_triplet}\"],\n        cwd=repo_dir,\n        check=False,\n    )\n\n    print(\"  Running vcpkg install ...\")\n    result = run(\n        [\n            vcpkg_bin,\n            \"install\",\n            f\"dispenso:{default_triplet}\",\n            f\"--overlay-ports={os.path.join(repo_dir, 'ports', 'dispenso')}\",\n            \"--no-binarycaching\",\n        ],\n        cwd=repo_dir,\n        check=False,\n    )\n    if result.returncode != 0:\n        print(\"  FAIL: vcpkg install failed\")\n        return False\n\n    print(\"  PASS: vcpkg install succeeded\")\n    return True\n\n\ndef test_homebrew(repo_dir, version):\n    \"\"\"Test homebrew formula with brew install, test, and audit.\"\"\"\n    brew_bin = shutil.which(\"brew\")\n    if not brew_bin:\n        print(\"  WARNING: brew not found — full testing requires macOS\")\n        return False\n\n    brew_repo = subprocess.run(\n        [brew_bin, \"--repository\"],\n        capture_output=True,\n        text=True,\n        check=True,\n    ).stdout.strip()\n\n    real_core = os.path.join(brew_repo, \"Library\", \"Taps\", \"homebrew\", \"homebrew-core\")\n    backup_core = None\n\n    try:\n        # Swap in our local checkout as homebrew-core\n        if os.path.exists(real_core):\n            backup_core = f\"{real_core}.bak.{os.getpid()}\"\n            print(\"  Temporarily replacing homebrew-core tap ...\")\n            os.rename(real_core, backup_core)\n        os.symlink(repo_dir, real_core)\n\n        # Uninstall if already installed\n        run([brew_bin, \"uninstall\", \"dispenso\"], check=False)\n\n        # Install from source\n        print(\n            \"  Running HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source ...\"\n        )\n        brew_env = {**os.environ, \"HOMEBREW_NO_INSTALL_FROM_API\": \"1\"}\n        result = run(\n            [brew_bin, \"install\", \"--build-from-source\", \"dispenso\"],\n            check=False,\n            capture=True,\n            env=brew_env,\n        )\n        if result.returncode != 0:\n            print(f\"  FAIL: brew install failed\\n{result.stderr}\")\n            return False\n\n        # Run tests\n        print(\"  Running brew test ...\")\n        result = run([brew_bin, \"test\", \"dispenso\"], check=False)\n        if result.returncode != 0:\n            print(\"  FAIL: brew test failed\")\n            return False\n\n        # Audit\n        print(\"  Running brew audit --strict ...\")\n        result = run([brew_bin, \"audit\", \"--strict\", \"dispenso\"], check=False)\n        if result.returncode != 0:\n            print(\"  WARNING: brew audit --strict reported issues\")\n\n        print(\"  PASS: homebrew tests succeeded\")\n        return True\n\n    finally:\n        # Restore original homebrew-core tap\n        if os.path.islink(real_core):\n            os.unlink(real_core)\n        if backup_core and os.path.exists(backup_core):\n            print(\"  Restoring original homebrew-core tap ...\")\n            os.rename(backup_core, real_core)\n        # Clean up\n        run([brew_bin, \"uninstall\", \"dispenso\"], check=False)\n\n\ndef test_macports(repo_dir, version, hashes=None):\n    \"\"\"Test macports portfile with port lint, install, and test.\"\"\"\n    # Verify checksums first — this catches the most common error\n    if hashes:\n        print(\"  --- Verifying checksums ---\")\n        if not verify_portfile_checksums(repo_dir, hashes):\n            print(\"  FAIL: checksum verification failed — fix before continuing\")\n            return False\n\n    port_bin = shutil.which(\"port\")\n    if not port_bin:\n        print(\"  WARNING: port not found — install MacPorts to run full tests\")\n        return False\n\n    portdir = os.path.join(repo_dir, \"devel\", \"dispenso\")\n\n    print(\"  Running port lint --nitpick ...\")\n    result = run(\n        [port_bin, \"-D\", portdir, \"lint\", \"--nitpick\"],\n        check=False,\n    )\n    if result.returncode != 0:\n        print(\"  FAIL: port lint failed\")\n        return False\n    print(\"  PASS: port lint succeeded\")\n\n    # Install and test require sudo.  Root cannot access files under the\n    # user's home directory on macOS, so copy to /tmp.  Running sudo from a\n    # Python subprocess may also be blocked by endpoint security tools, so\n    # print the commands for the user to run manually.\n    tmp_parent = tempfile.mkdtemp(prefix=\"dispenso-port-\", dir=\"/tmp\")\n    os.chmod(tmp_parent, 0o755)\n    tmp_portdir = os.path.join(tmp_parent, \"dispenso\")\n    shutil.copytree(portdir, tmp_portdir)\n    for dirpath, dirs, files in os.walk(tmp_portdir):\n        for d in dirs:\n            os.chmod(os.path.join(dirpath, d), 0o755)\n        for f in files:\n            os.chmod(os.path.join(dirpath, f), 0o644)\n\n    print()\n    print(\"  The next steps require sudo.  Please run each command manually\")\n    print(\"  in a separate terminal, then come back and report the result.\")\n\n    install_ok = False\n    test_ok = False\n    install_note = \"\"\n    test_note = \"\"\n\n    # Step 1: install\n    print()\n    print(\"  Step 1 — run this command:\")\n    print(f\"    sudo {port_bin} -D {tmp_portdir} -vst install\")\n    print()\n    answer = input(\"  Result? [y=succeeded / or describe what happened] \").strip()\n    if answer.lower() == \"y\":\n        install_ok = True\n        print(\"  PASS: port install (user-confirmed)\")\n    else:\n        install_note = answer\n        print(f\"  NOTED: port install issue — {answer}\")\n\n    # Step 2: test\n    print()\n    print(\"  Step 2 — run this command:\")\n    print(f\"    sudo {port_bin} -D {tmp_portdir} test\")\n    print()\n    answer = input(\"  Result? [y=succeeded / or describe what happened] \").strip()\n    if answer.lower() == \"y\":\n        test_ok = True\n        print(\"  PASS: port test (user-confirmed)\")\n    else:\n        test_note = answer\n        print(f\"  NOTED: port test issue — {answer}\")\n\n    # Summarize\n    print()\n    if install_ok and test_ok:\n        print(\"  PASS: port install + test both succeeded\")\n    elif test_ok and not install_ok:\n        print(\"  PARTIAL: port test passed but install had issues\")\n        print(f\"    install note: {install_note}\")\n    elif install_ok and not test_ok:\n        print(\"  PARTIAL: port install passed but test had issues\")\n        print(f\"    test note: {test_note}\")\n    else:\n        print(\"  FAIL: both install and test had issues\")\n\n    if not (install_ok and test_ok):\n        print(f\"  (temp port dir preserved at {tmp_portdir} for debugging)\")\n    else:\n        shutil.rmtree(tmp_parent, ignore_errors=True)\n\n    return test_ok\n\n\ndef get_macos_tested_on():\n    \"\"\"Gather macOS system info for MacPorts 'Tested on' PR section.\n\n    Returns a formatted string matching the MacPorts PR template, or None\n    if not running on macOS.\n    \"\"\"\n    if platform.system() != \"Darwin\":\n        return None\n\n    lines = []\n\n    # macOS version + build + arch\n    result = subprocess.run(\n        [\"sw_vers\", \"-productVersion\"], capture_output=True, text=True\n    )\n    if result.returncode == 0:\n        mac_ver = result.stdout.strip()\n        build_result = subprocess.run(\n            [\"sw_vers\", \"-buildVersion\"], capture_output=True, text=True\n        )\n        build = build_result.stdout.strip() if build_result.returncode == 0 else \"\"\n        arch_result = subprocess.run([\"uname\", \"-m\"], capture_output=True, text=True)\n        arch = arch_result.stdout.strip() if arch_result.returncode == 0 else \"\"\n        lines.append(f\"macOS {mac_ver} {build} {arch}\")\n\n    # Xcode or Command Line Tools version\n    result = subprocess.run([\"xcodebuild\", \"-version\"], capture_output=True, text=True)\n    if result.returncode == 0:\n        parts = result.stdout.strip().split(\"\\n\")\n        if len(parts) >= 2:\n            # \"Xcode 16.2\\nBuild version 16C5032a\" → \"Xcode 16.2 16C5032a\"\n            lines.append(f\"{parts[0]} {parts[-1].split()[-1]}\")\n        elif parts:\n            lines.append(parts[0])\n    else:\n        result = subprocess.run(\n            [\"pkgutil\", \"--pkg-info=com.apple.pkg.CLTools_Executables\"],\n            capture_output=True,\n            text=True,\n        )\n        if result.returncode == 0:\n            for line in result.stdout.split(\"\\n\"):\n                if \"version:\" in line:\n                    lines.append(f\"Command Line Tools {line.split(':')[1].strip()}\")\n                    break\n\n    return \"\\n\".join(lines) if lines else None\n\n\n# ---------------------------------------------------------------------------\n# Post-write checksum verification\n# ---------------------------------------------------------------------------\n\nMACOS_ONLY_MANAGERS = {\"homebrew\", \"macports\"}\n\n\ndef verify_portfile_checksums(repo_dir, hashes):\n    \"\"\"Verify that the Portfile checksums match the computed hashes.\"\"\"\n    portfile_path = os.path.join(repo_dir, \"devel\", \"dispenso\", \"Portfile\")\n    content = open(portfile_path).read()\n\n    ok = True\n    for field, key in [(\"rmd160\", \"rmd160\"), (\"sha256\", \"sha256\"), (\"size\", \"size\")]:\n        match = re.search(rf\"{field}\\s+(\\S+)\", content)\n        if not match:\n            print(f\"  WARNING: {field} not found in Portfile\")\n            continue\n        expected = str(hashes[key])\n        actual = match.group(1)\n        if actual != expected:\n            print(f\"  FAIL: {field} mismatch in Portfile\")\n            print(f\"    Portfile:  {actual}\")\n            print(f\"    Expected:  {expected}\")\n            ok = False\n\n    if ok:\n        print(\"  PASS: Portfile checksums match computed hashes\")\n    return ok\n\n\ndef verify_formula_checksums(repo_dir, hashes):\n    \"\"\"Verify that the Homebrew formula sha256 matches the computed hash.\"\"\"\n    formula_path = os.path.join(repo_dir, \"Formula\", \"d\", \"dispenso.rb\")\n    content = open(formula_path).read()\n\n    match = re.search(r'sha256\\s+\"([0-9a-fA-F]+)\"', content)\n    if not match:\n        print(\"  WARNING: sha256 not found in formula\")\n        return False\n\n    expected = hashes[\"sha256\"]\n    actual = match.group(1)\n    if actual != expected:\n        print(\"  FAIL: sha256 mismatch in formula\")\n        print(f\"    Formula:   {actual}\")\n        print(f\"    Expected:  {expected}\")\n        return False\n\n    print(\"  PASS: Formula sha256 matches computed hash\")\n    return True\n\n\n# ---------------------------------------------------------------------------\n# Per-manager update functions\n# ---------------------------------------------------------------------------\n\n\ndef ensure_conan_issue(version, github_user, dry_run):\n    \"\"\"Search for or create a Conan Center Index issue for this version.\n\n    Returns the issue number if found/created, or None on failure.\n    \"\"\"\n    repo = UPSTREAM_REPOS[\"conan\"]\n    search_query = f\"[package] dispenso/{version}\"\n\n    # Search for existing issue\n    print(f\"  Searching for existing Conan issue: {search_query}\")\n    if dry_run:\n        print(f\"  [DRY RUN] Would search/create issue for dispenso/{version}\")\n        return None\n\n    result = subprocess.run(\n        [\n            \"gh\",\n            \"search\",\n            \"issues\",\n            search_query,\n            \"--repo\",\n            repo,\n            \"--json\",\n            \"number,title\",\n            \"--limit\",\n            \"5\",\n        ],\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0 and result.stdout.strip():\n        try:\n            issues = json.loads(result.stdout)\n            for issue in issues:\n                if f\"dispenso/{version}\" in issue.get(\"title\", \"\"):\n                    number = issue[\"number\"]\n                    print(f\"  Found existing issue #{number}: {issue['title']}\")\n                    return number\n        except (json.JSONDecodeError, KeyError):\n            pass\n\n    # Create new issue\n    print(f\"  Creating new Conan issue for dispenso/{version} ...\")\n    issue_body = f\"\"\"\\\n### Package Details\n- **Name**: dispenso\n- **Version**: {version}\n- **Homepage**: https://github.com/facebookincubator/dispenso\n- **License**: MIT\n\n### Description\ndispenso is a high-performance C++ library for parallel programming from Meta. \\\nIt provides work-stealing thread pools, parallel for loops, futures, task graphs, \\\npipelines, and concurrent containers. Requires C++14, no external dependencies \\\nbeyond pthreads.\"\"\"\n\n    result = subprocess.run(\n        [\n            \"gh\",\n            \"issue\",\n            \"create\",\n            \"--repo\",\n            repo,\n            \"--title\",\n            f\"[package] dispenso/{version}\",\n            \"--body\",\n            issue_body,\n        ],\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        # Output is the issue URL, extract number from it\n        url = result.stdout.strip()\n        match = re.search(r\"/issues/(\\d+)\", url)\n        if match:\n            number = int(match.group(1))\n            print(f\"  Created issue #{number}: {url}\")\n            return number\n        print(f\"  Created issue: {url}\")\n        return None\n\n    print(f\"  WARNING: Failed to create Conan issue: {result.stderr.strip()}\")\n    return None\n\n\ndef update_conan(args, hashes, tarball_path):\n    \"\"\"Update conan-center-index with new dispenso version.\"\"\"\n    print(\"=== Conan (conan-center-index) ===\")\n    version = args.version\n    manager = \"conan\"\n    branch = BRANCH_NAMES.get(manager, \"add-dispenso\")\n\n    repo_dir = ensure_repo(args.repos_dir, manager, args.github_user, args.dry_run)\n    checkout_branch(repo_dir, branch, args.dry_run)\n\n    # --- Update conandata.yml ---\n    conandata_path = os.path.join(\n        repo_dir, \"recipes\", \"dispenso\", \"all\", \"conandata.yml\"\n    )\n    print(f\"  Updating {conandata_path} ...\")\n\n    if not args.dry_run:\n        content = open(conandata_path).read()\n\n        # Check if version already present\n        if f'\"{version}\"' in content:\n            print(f\"  Version {version} already present in conandata.yml\")\n        else:\n            # Insert new version entry right after \"sources:\\n\"\n            new_entry = (\n                f'  \"{version}\":\\n'\n                f'    url: \"{hashes[\"url\"]}\"\\n'\n                f'    sha256: \"{hashes[\"sha256\"]}\"\\n'\n            )\n            content = content.replace(\"sources:\\n\", f\"sources:\\n{new_entry}\", 1)\n            open(conandata_path, \"w\").write(content)\n            print(f\"  Added version {version} to conandata.yml\")\n    else:\n        print(f\"  [DRY RUN] Would add {version} entry with sha256={hashes['sha256']}\")\n\n    # --- Update config.yml ---\n    config_path = os.path.join(repo_dir, \"recipes\", \"dispenso\", \"config.yml\")\n    print(f\"  Updating {config_path} ...\")\n\n    if not args.dry_run:\n        content = open(config_path).read()\n\n        if f'\"{version}\"' in content:\n            print(f\"  Version {version} already present in config.yml\")\n        else:\n            new_entry = f'  \"{version}\":\\n    folder: all\\n'\n            content = content.replace(\"versions:\\n\", f\"versions:\\n{new_entry}\", 1)\n            open(config_path, \"w\").write(content)\n            print(f\"  Added version {version} to config.yml\")\n    else:\n        print(f\"  [DRY RUN] Would add {version} entry to config.yml\")\n\n    # --- Ensure GitHub issue exists ---\n    print(\"  --- Conan issue ---\")\n    issue_number = ensure_conan_issue(version, args.github_user, args.dry_run)\n\n    # --- Commit ---\n    commit_msg = f\"dispenso: add version {version}\"\n    committed = commit_and_push(\n        repo_dir, branch, commit_msg, args.github_user, args.dry_run, skip_push=True\n    )\n\n    # --- Test ---\n    test_passed = True\n    if committed and not args.dry_run and not args.skip_test:\n        print(\"  --- Testing ---\")\n        test_passed = test_conan(repo_dir, version)\n\n    # --- Push ---\n    if not committed:\n        print(\"  Skipping push — no changes to push\")\n    elif not args.dry_run and not args.skip_push:\n        if not test_passed:\n            print(\"  Skipping push due to test failure\")\n        else:\n            run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n\n    branch_url = (\n        f\"https://github.com/{args.github_user}/conan-center-index/tree/{branch}\"\n    )\n    tests_ran = not args.skip_test and not args.dry_run and test_passed\n    title = pr_title(\"conan\", version)\n    body = pr_body_conan(version, tests_ran=tests_ran, issue_number=issue_number)\n    print()\n    return {\n        \"status\": \"no_changes\"\n        if not committed\n        else \"ok\"\n        if test_passed\n        else \"test_failed\",\n        \"branch\": branch,\n        \"branch_url\": branch_url,\n        \"version\": version,\n        \"tests_ran\": tests_ran,\n        \"pr_title\": title,\n        \"pr_body\": body,\n    }\n\n\ndef detect_obsolete_patches(tarball_path, port_dir, strip_level=1):\n    \"\"\"Check which patches in port_dir are obsolete against the tarball source.\n\n    Extracts the tarball to a temp directory and tries `git apply --check` for\n    each .patch file. Returns a list of patch filenames that no longer apply\n    (i.e. the fix has been upstreamed).\n\n    Args:\n        strip_level: Number of leading path components to strip (0 for MacPorts,\n            1 for vcpkg/git-style patches).\n    \"\"\"\n    patch_files = [f for f in os.listdir(port_dir) if f.endswith(\".patch\")]\n    if not patch_files:\n        return []\n\n    obsolete = []\n    tmpdir = tempfile.mkdtemp(prefix=\"dispenso-patch-check-\")\n    try:\n        # Extract tarball\n        with tarfile.open(tarball_path, \"r:gz\") as tf:\n            tf.extractall(tmpdir, filter=\"data\")\n\n        # Find the extracted directory (e.g. dispenso-1.5.1/)\n        entries = os.listdir(tmpdir)\n        if len(entries) == 1 and os.path.isdir(os.path.join(tmpdir, entries[0])):\n            src_dir = os.path.join(tmpdir, entries[0])\n        else:\n            src_dir = tmpdir\n\n        # Initialize a temporary git repo so we can use git apply --check\n        subprocess.run([\"git\", \"init\"], cwd=src_dir, capture_output=True, check=True)\n        subprocess.run(\n            [\"git\", \"add\", \"-A\"], cwd=src_dir, capture_output=True, check=True\n        )\n        subprocess.run(\n            [\"git\", \"commit\", \"-m\", \"initial\"],\n            cwd=src_dir,\n            capture_output=True,\n            check=True,\n        )\n\n        for patch_file in patch_files:\n            patch_path = os.path.join(port_dir, patch_file)\n            result = subprocess.run(\n                [\"git\", \"apply\", \"--check\", f\"-p{strip_level}\", patch_path],\n                cwd=src_dir,\n                capture_output=True,\n            )\n            if result.returncode != 0:\n                print(f\"  Patch {patch_file}: OBSOLETE (no longer applies)\")\n                obsolete.append(patch_file)\n            else:\n                print(f\"  Patch {patch_file}: still needed (applies cleanly)\")\n\n    finally:\n        shutil.rmtree(tmpdir, ignore_errors=True)\n\n    return obsolete\n\n\ndef remove_obsolete_patches(port_dir, portfile_path, obsolete_patches):\n    \"\"\"Remove obsolete patches from portfile.cmake and delete patch files.\"\"\"\n    if not obsolete_patches:\n        return\n\n    content = open(portfile_path).read()\n\n    for patch_file in obsolete_patches:\n        # Delete the patch file\n        patch_path = os.path.join(port_dir, patch_file)\n        if os.path.exists(patch_path):\n            os.unlink(patch_path)\n            print(f\"  Deleted {patch_file}\")\n\n    # Check if there are remaining patches\n    remaining = [f for f in os.listdir(port_dir) if f.endswith(\".patch\")]\n\n    if not remaining:\n        # Remove entire PATCHES block from portfile.cmake\n        # Match: PATCHES\\n    file1.patch\\n    file2.patch\\n (up to next keyword or end)\n        content = re.sub(\n            r\"\\s+PATCHES\\n(?:\\s+\\S+\\.patch\\n?)+\",\n            \"\\n\",\n            content,\n        )\n        print(\"  Removed entire PATCHES block from portfile.cmake\")\n    else:\n        # Remove only obsolete patch filenames from PATCHES block\n        for patch_file in obsolete_patches:\n            # Remove the line \"    patch_file.patch\\n\"\n            content = re.sub(\n                rf\"\\s+{re.escape(patch_file)}\\n?\",\n                \"\\n\",\n                content,\n            )\n        print(f\"  Removed obsolete patches from portfile.cmake, kept: {remaining}\")\n\n    open(portfile_path, \"w\").write(content)\n\n\ndef _vcpkg_update_port_files(repo_dir, version, hashes, dry_run):\n    \"\"\"Update vcpkg.json version/port-version and portfile.cmake SHA512.\"\"\"\n    vcpkg_json_path = os.path.join(repo_dir, \"ports\", \"dispenso\", \"vcpkg.json\")\n    print(f\"  Updating {vcpkg_json_path} ...\")\n\n    if not dry_run:\n        content = open(vcpkg_json_path).read()\n        content = re.sub(\n            r'\"version\"\\s*:\\s*\"[^\"]*\"',\n            f'\"version\": \"{version}\"',\n            content,\n        )\n        # Remove port-version (resets to 0 on version bump)\n        content = re.sub(r',?\\s*\"port-version\"\\s*:\\s*\\d+', \"\", content)\n        open(vcpkg_json_path, \"w\").write(content)\n        print(f\"  Updated version to {version} (removed port-version if present)\")\n    else:\n        print(f\"  [DRY RUN] Would update version to {version} (remove port-version)\")\n\n    portfile_path = os.path.join(repo_dir, \"ports\", \"dispenso\", \"portfile.cmake\")\n    print(f\"  Updating {portfile_path} ...\")\n\n    if not dry_run:\n        content = open(portfile_path).read()\n        content = re.sub(\n            r\"SHA512\\s+[0-9a-fA-F]+\",\n            f\"SHA512 {hashes['sha512']}\",\n            content,\n        )\n        open(portfile_path, \"w\").write(content)\n        print(\"  Updated SHA512\")\n    else:\n        print(f\"  [DRY RUN] Would update SHA512 to {hashes['sha512']}\")\n\n    return vcpkg_json_path\n\n\ndef _vcpkg_cleanup_patches(repo_dir, tarball_path, dry_run):\n    \"\"\"Detect and remove obsolete patches from the vcpkg port.\"\"\"\n    port_dir = os.path.join(repo_dir, \"ports\", \"dispenso\")\n    portfile_path = os.path.join(port_dir, \"portfile.cmake\")\n\n    if dry_run or not os.path.isdir(port_dir):\n        return\n    patch_files = [f for f in os.listdir(port_dir) if f.endswith(\".patch\")]\n    if not patch_files:\n        return\n\n    print(\"  --- Checking patches against new source ---\")\n    obsolete = detect_obsolete_patches(tarball_path, port_dir)\n    if obsolete:\n        remove_obsolete_patches(port_dir, portfile_path, obsolete)\n\n\ndef _macports_cleanup_patches(repo_dir, tarball_path, dry_run):\n    \"\"\"Detect and remove obsolete patches from the MacPorts port.\n\n    MacPorts patches use -p0 (no a/b prefixes) and are stored in a files/\n    subdirectory. The Portfile references them via 'patchfiles'.\n    \"\"\"\n    port_dir = os.path.join(repo_dir, \"devel\", \"dispenso\")\n    files_dir = os.path.join(port_dir, \"files\")\n\n    if dry_run or not os.path.isdir(files_dir):\n        return\n\n    patch_files = [f for f in os.listdir(files_dir) if f.endswith(\".patch\")]\n    if not patch_files:\n        return\n\n    print(\"  --- Checking patches against new source ---\")\n    obsolete = detect_obsolete_patches(tarball_path, files_dir, strip_level=0)\n    if not obsolete:\n        return\n\n    portfile_path = os.path.join(port_dir, \"Portfile\")\n\n    # Delete obsolete patch files\n    for patch_file in obsolete:\n        patch_path = os.path.join(files_dir, patch_file)\n        if os.path.exists(patch_path):\n            os.unlink(patch_path)\n            print(f\"  Deleted {patch_file}\")\n\n    # Check if any patches remain\n    remaining = [f for f in os.listdir(files_dir) if f.endswith(\".patch\")]\n\n    # Update Portfile: remove patchfiles entries\n    content = open(portfile_path).read()\n    if not remaining:\n        # Remove entire patchfiles line(s)\n        content = re.sub(r\"\\n*patchfiles\\s+.*\\n?\", \"\\n\", content)\n        print(\"  Removed patchfiles from Portfile\")\n        # Remove empty files/ directory\n        try:\n            os.rmdir(files_dir)\n            print(\"  Removed empty files/ directory\")\n        except OSError:\n            pass\n    else:\n        # Remove only obsolete entries from patchfiles\n        for patch_file in obsolete:\n            content = re.sub(rf\"\\s*{re.escape(patch_file)}\", \"\", content)\n        print(f\"  Removed obsolete patches from Portfile, kept: {remaining}\")\n\n    open(portfile_path, \"w\").write(content)\n\n\ndef _vcpkg_run_tooling(repo_dir, vcpkg_json_path, dry_run):\n    \"\"\"Run vcpkg format-manifest and x-add-version if vcpkg is available.\"\"\"\n    vcpkg_bin = shutil.which(\"vcpkg\")\n    if not vcpkg_bin:\n        print(\n            \"  WARNING: vcpkg not found. Run 'vcpkg format-manifest' and \"\n            \"'vcpkg x-add-version dispenso --overlay-ports=ports/dispenso' \"\n            \"manually before pushing.\"\n        )\n        return\n\n    print(\"  Running vcpkg format-manifest ...\")\n    run(\n        [vcpkg_bin, \"format-manifest\", vcpkg_json_path],\n        cwd=repo_dir,\n        check=False,\n        dry_run=dry_run,\n    )\n\n    # x-add-version requires port changes to be committed first, so we make\n    # a temporary commit. The final commit_and_push will squash everything.\n    print(\"  Running vcpkg x-add-version ...\")\n    if not dry_run:\n        run([\"git\", \"add\", \"-A\"], cwd=repo_dir)\n        result = subprocess.run([\"git\", \"diff\", \"--cached\", \"--quiet\"], cwd=repo_dir)\n        if result.returncode != 0:\n            run(\n                [\"git\", \"commit\", \"-m\", \"temp: port changes for x-add-version\"],\n                cwd=repo_dir,\n            )\n    run(\n        [\n            vcpkg_bin,\n            \"x-add-version\",\n            \"dispenso\",\n            \"--overwrite-version\",\n            f\"--overlay-ports={os.path.join(repo_dir, 'ports', 'dispenso')}\",\n        ],\n        cwd=repo_dir,\n        check=False,\n        dry_run=dry_run,\n    )\n    # Version database changes from x-add-version will be staged by\n    # commit_and_push's git add -A.\n\n\ndef _vcpkg_verify_port_files(repo_dir, version, hashes):\n    \"\"\"Verify port files contain the expected version and hash after updates.\"\"\"\n    port_dir = os.path.join(repo_dir, \"ports\", \"dispenso\")\n    errors = []\n\n    vcpkg_json_path = os.path.join(port_dir, \"vcpkg.json\")\n    portfile_path = os.path.join(port_dir, \"portfile.cmake\")\n\n    # Check vcpkg.json has correct version\n    vcpkg_json = open(vcpkg_json_path).read()\n    if f'\"version\": \"{version}\"' not in vcpkg_json:\n        errors.append(f\"vcpkg.json does not contain version {version}\")\n\n    # Check portfile.cmake has correct SHA512\n    portfile = open(portfile_path).read()\n    if hashes[\"sha512\"] not in portfile:\n        errors.append(\"portfile.cmake does not contain expected SHA512\")\n\n    # Check portfile doesn't reference deleted patch files.\n    # Only match lines that look like bare filenames (no spaces, no comment chars).\n    for line in portfile.splitlines():\n        stripped = line.strip()\n        if (\n            stripped.endswith(\".patch\")\n            and \" \" not in stripped\n            and not stripped.startswith(\"#\")\n        ):\n            patch_path = os.path.join(port_dir, stripped)\n            if not os.path.exists(patch_path):\n                errors.append(\n                    f\"portfile.cmake references {stripped} but file does not exist\"\n                )\n\n    if errors:\n        print(\"  ERROR: Port file verification failed:\")\n        for e in errors:\n            print(f\"    - {e}\")\n        raise RuntimeError(\"vcpkg port files are inconsistent; aborting\")\n    else:\n        print(\"  Verified: vcpkg.json and portfile.cmake are consistent\")\n\n\ndef update_vcpkg(args, hashes, tarball_path):\n    \"\"\"Update vcpkg with new dispenso version.\"\"\"\n    print(\"=== vcpkg ===\")\n    version = args.version\n    manager = \"vcpkg\"\n    branch = BRANCH_NAMES.get(manager, \"add-dispenso\")\n\n    repo_dir = ensure_repo(args.repos_dir, manager, args.github_user, args.dry_run)\n    checkout_branch(repo_dir, branch, args.dry_run)\n\n    vcpkg_json_path = _vcpkg_update_port_files(repo_dir, version, hashes, args.dry_run)\n    _vcpkg_cleanup_patches(repo_dir, tarball_path, args.dry_run)\n    _vcpkg_run_tooling(repo_dir, vcpkg_json_path, args.dry_run)\n\n    # Verify port files were updated correctly before committing.\n    if not args.dry_run:\n        _vcpkg_verify_port_files(repo_dir, version, hashes)\n\n    # --- Commit ---\n    commit_msg = f\"[dispenso] Update to version {version}\"\n    committed = commit_and_push(\n        repo_dir, branch, commit_msg, args.github_user, args.dry_run, skip_push=True\n    )\n\n    # --- Test ---\n    test_passed = True\n    if committed and not args.dry_run and not args.skip_test:\n        print(\"  --- Testing ---\")\n        test_passed = test_vcpkg(repo_dir, version)\n\n    # --- Push ---\n    if not committed:\n        print(\"  Skipping push — no changes to push\")\n    elif not args.dry_run and not args.skip_push:\n        if not test_passed:\n            print(\"  Skipping push due to test failure\")\n        else:\n            run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n\n    branch_url = f\"https://github.com/{args.github_user}/vcpkg/tree/{branch}\"\n    tests_ran = committed and not args.skip_test and not args.dry_run and test_passed\n    title = pr_title(\"vcpkg\", version)\n    body = pr_body_vcpkg(version)\n    print()\n    return {\n        \"status\": \"no_changes\"\n        if not committed\n        else \"ok\"\n        if test_passed\n        else \"test_failed\",\n        \"branch\": branch,\n        \"branch_url\": branch_url,\n        \"version\": version,\n        \"tests_ran\": tests_ran,\n        \"pr_title\": title,\n        \"pr_body\": body,\n    }\n\n\ndef update_homebrew(args, hashes, tarball_path):\n    \"\"\"Update homebrew-core with new dispenso version.\"\"\"\n    print(\"=== Homebrew (homebrew-core) ===\")\n    version = args.version\n    manager = \"homebrew\"\n    branch = f\"dispenso-{version}\"\n\n    repo_dir = ensure_repo(args.repos_dir, manager, args.github_user, args.dry_run)\n    checkout_branch(repo_dir, branch, args.dry_run)\n\n    formula_path = os.path.join(repo_dir, \"Formula\", \"d\", \"dispenso.rb\")\n    print(f\"  Updating {formula_path} ...\")\n\n    if not args.dry_run:\n        if not os.path.exists(formula_path):\n            print(f\"  ERROR: Formula file not found at {formula_path}\")\n            print(\"  The dispenso formula may not exist yet in homebrew-core.\")\n            print()\n            return {\"status\": \"error\", \"error\": \"Formula file not found\"}\n\n        content = open(formula_path).read()\n\n        # Update url\n        content = re.sub(\n            r'url\\s+\"https://github\\.com/facebookincubator/dispenso/archive/refs/tags/v[^\"]+\\.tar\\.gz\"',\n            f'url \"https://github.com/{GITHUB_REPO}/archive/refs/tags/v{version}.tar.gz\"',\n            content,\n        )\n\n        # Update sha256\n        content = re.sub(\n            r'sha256\\s+\"[0-9a-fA-F]+\"',\n            f'sha256 \"{hashes[\"sha256\"]}\"',\n            content,\n        )\n\n        # Remove revision line (reset on version bump)\n        content = re.sub(r\"\\n\\s*revision\\s+\\d+\", \"\", content)\n\n        open(formula_path, \"w\").write(content)\n        print(\"  Updated url, sha256 (removed revision if present)\")\n    else:\n        print(\"  [DRY RUN] Would update url and sha256 in formula\")\n\n    # --- Verify checksums ---\n    checksums_ok = True\n    if not args.dry_run:\n        print(\"  --- Verifying checksums ---\")\n        checksums_ok = verify_formula_checksums(repo_dir, hashes)\n\n    # --- Commit ---\n    commit_msg = f\"dispenso {version}\"\n    committed = commit_and_push(\n        repo_dir, branch, commit_msg, args.github_user, args.dry_run, skip_push=True\n    )\n\n    # --- Test ---\n    fully_tested = False\n    if committed and checksums_ok and not args.dry_run and not args.skip_test:\n        print(\"  --- Testing ---\")\n        fully_tested = test_homebrew(repo_dir, version)\n\n    # --- Push ---\n    if not committed:\n        print(\"  Skipping push — no changes to push\")\n    elif not args.dry_run and not args.skip_push:\n        if not checksums_ok:\n            print(\"  Skipping push due to checksum verification failure\")\n        else:\n            run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n\n    branch_url = f\"https://github.com/{args.github_user}/homebrew-core/tree/{branch}\"\n    title = pr_title(\"homebrew\", version)\n    body = pr_body_homebrew(version, tests_ran=fully_tested)\n    print()\n    return {\n        \"status\": \"no_changes\"\n        if not committed\n        else \"error\"\n        if not checksums_ok\n        else \"ok\"\n        if fully_tested or args.skip_test\n        else \"needs_macos\",\n        \"branch\": branch,\n        \"branch_url\": branch_url,\n        \"version\": version,\n        \"tests_ran\": fully_tested,\n        \"pr_title\": title,\n        \"pr_body\": body,\n    }\n\n\ndef update_macports(args, hashes, tarball_path):\n    \"\"\"Update macports-ports with new dispenso version.\"\"\"\n    print(\"=== MacPorts (macports-ports) ===\")\n    version = args.version\n    manager = \"macports\"\n    branch = f\"dispenso-{version}\"\n\n    if hashes[\"rmd160\"] is None:\n        print(\"  ERROR: RIPEMD-160 hash not available, cannot update MacPorts\")\n        print()\n        return {\"status\": \"error\", \"error\": \"RIPEMD-160 hash not available\"}\n\n    repo_dir = ensure_repo(args.repos_dir, manager, args.github_user, args.dry_run)\n    checkout_branch(repo_dir, branch, args.dry_run)\n\n    portfile_path = os.path.join(repo_dir, \"devel\", \"dispenso\", \"Portfile\")\n    print(f\"  Updating {portfile_path} ...\")\n\n    if not args.dry_run:\n        if not os.path.exists(portfile_path):\n            print(f\"  ERROR: Portfile not found at {portfile_path}\")\n            print(\"  The dispenso port may not exist yet in MacPorts.\")\n            print()\n            return {\"status\": \"error\", \"error\": \"Portfile not found\"}\n\n        content = open(portfile_path).read()\n\n        # Update github.setup line version\n        content = re.sub(\n            r\"(github\\.setup\\s+facebookincubator\\s+dispenso\\s+)\\S+(\\s+v)\",\n            rf\"\\g<1>{version}\\2\",\n            content,\n        )\n\n        # Update checksums block\n        content = re.sub(\n            r\"(checksums\\s+rmd160\\s+)\\S+\",\n            rf\"\\g<1>{hashes['rmd160']}\",\n            content,\n        )\n        content = re.sub(\n            r\"(sha256\\s+)\\S+\",\n            rf\"\\g<1>{hashes['sha256']}\",\n            content,\n        )\n        content = re.sub(\n            r\"(size\\s+)\\S+\",\n            rf\"\\g<1>{hashes['size']}\",\n            content,\n        )\n\n        # Reset revision to 0 if present\n        content = re.sub(\n            r\"(revision\\s+)\\d+\",\n            r\"\\g<1>0\",\n            content,\n        )\n\n        open(portfile_path, \"w\").write(content)\n        print(\"  Updated github.setup version, checksums (rmd160, sha256, size)\")\n    else:\n        print(f\"  [DRY RUN] Would update version to {version} and checksums\")\n\n    # --- Verify checksums ---\n    checksums_ok = True\n    if not args.dry_run:\n        print(\"  --- Verifying checksums ---\")\n        checksums_ok = verify_portfile_checksums(repo_dir, hashes)\n\n    # --- Clean up obsolete patches ---\n    _macports_cleanup_patches(repo_dir, tarball_path, args.dry_run)\n\n    # --- Commit ---\n    commit_msg = f\"dispenso: update to {version}\"\n    committed = commit_and_push(\n        repo_dir, branch, commit_msg, args.github_user, args.dry_run, skip_push=True\n    )\n\n    # --- Test ---\n    fully_tested = False\n    tested_on = None\n    if committed and checksums_ok and not args.dry_run and not args.skip_test:\n        print(\"  --- Testing ---\")\n        fully_tested = test_macports(repo_dir, version, hashes=hashes)\n        if fully_tested:\n            tested_on = get_macos_tested_on()\n\n    # --- Push ---\n    if not committed:\n        print(\"  Skipping push — no changes to push\")\n    elif not args.dry_run and not args.skip_push:\n        if not checksums_ok:\n            print(\"  Skipping push due to checksum verification failure\")\n        else:\n            run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n\n    branch_url = f\"https://github.com/{args.github_user}/macports-ports/tree/{branch}\"\n    title = pr_title(\"macports\", version)\n    body = pr_body_macports(version, tests_ran=fully_tested, tested_on=tested_on)\n    print()\n    return {\n        \"status\": \"no_changes\"\n        if not committed\n        else \"error\"\n        if not checksums_ok\n        else \"ok\"\n        if fully_tested or args.skip_test\n        else \"needs_macos\",\n        \"branch\": branch,\n        \"branch_url\": branch_url,\n        \"version\": version,\n        \"tests_ran\": fully_tested,\n        \"pr_title\": title,\n        \"pr_body\": body,\n    }\n\n\n# ---------------------------------------------------------------------------\n# PR body templates\n# ---------------------------------------------------------------------------\n\n\ndef pr_body_homebrew(version, tests_ran):\n    \"\"\"Generate PR body following Homebrew's PR template.\"\"\"\n    test_check = \"[x]\" if tests_ran else \"[ ]\"\n    audit_line = (\n        f\"- {test_check} Does your build pass `brew audit --strict <formula>` \"\n        \"(after doing `HOMEBREW_NO_INSTALL_FROM_API=1 brew install \"\n        \"--build-from-source <formula>`)? If this is a new formula, \"\n        \"does it pass `brew audit --new <formula>`?\"\n    )\n    return f\"\"\"\\\n- [ ] Have you followed the [guidelines for contributing](https://github.com/Homebrew/homebrew-core/blob/HEAD/CONTRIBUTING.md)?\n- [x] Have you ensured that your commits follow the [commit style guide](https://docs.brew.sh/Formula-Cookbook#commit)?\n- [x] Have you checked that there aren't other open [pull requests](https://github.com/Homebrew/homebrew-core/pulls) for the same formula update/change?\n- {test_check} Have you built your formula locally with `HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source <formula>`?\n- {test_check} Is your test running fine `brew test <formula>`?\n{audit_line}\n\n-----\n\n- [x] AI was used to generate or assist with generating this PR. \\\nA script ([update_package_managers.py](https://github.com/facebookincubator/dispenso/blob/main/scripts/update_package_managers.py)) \\\nwas used to update the version, URL, and SHA256 in the formula. \\\nThe formula was verified locally before submission.\n\n-----\n\nUpdate dispenso to {version}.\n\n[dispenso](https://github.com/facebookincubator/dispenso) is a high-performance \\\nC++ library for parallel programming from Meta. It provides work-stealing thread \\\npools, parallel for loops, futures, task graphs, pipelines, and concurrent containers. \\\nRequires C++14, no external dependencies beyond pthreads.\"\"\"\n\n\ndef pr_body_conan(version, tests_ran, issue_number=None):\n    \"\"\"Generate PR body following Conan Center Index's PR template.\"\"\"\n    test_check = \"[x]\" if tests_ran else \"[ ]\"\n    issue_line = f\"\\nfixes #{issue_number}\\n\" if issue_number else \"\"\n    return f\"\"\"\\\n### Summary\nChanges to recipe:  **dispenso/{version}**\n{issue_line}\n#### Motivation\nUpdate dispenso to version {version}.\n\n#### Details\nAdded version {version} entry to `conandata.yml` and `config.yml`. \\\nNo changes to `conanfile.py` (version-agnostic).\n\n---\n- [x] Read the [contributing guidelines](https://github.com/conan-io/conan-center-index/blob/master/CONTRIBUTING.md)\n- [x] Checked that this PR is not a duplicate: [list of PRs by recipe](https://github.com/conan-io/conan-center-index/discussions/24240)\n- [ ] If this is a bug fix, please link related issue or provide bug details\n- {test_check} Tested locally with at least one configuration using a recent version of Conan\n---\"\"\"\n\n\ndef pr_body_vcpkg(version):\n    \"\"\"Generate PR body following vcpkg's PR template.\"\"\"\n    return f\"\"\"\\\n## Port Update Checklist\n\n- [x] Complies with the [maintainer guide](https://learn.microsoft.com/en-us/vcpkg/contributing/maintainer-guide)\n- [x] Updated SHA512 checksums\n- [x] Version database updated via `./vcpkg x-add-version --all`\n- [x] Exactly one version added per modified versions file\n\nUpdate dispenso to version {version}.\"\"\"\n\n\ndef pr_body_macports(version, tests_ran, tested_on=None):\n    \"\"\"Generate PR body following MacPorts' PR template.\"\"\"\n    test_check = \"[x]\" if tests_ran else \"[ ]\"\n    if tested_on:\n        tested_on_section = tested_on\n    else:\n        tested_on_section = (\n            \"<!-- Run and paste output of: \"\n            \"port version && sw_vers && xcode-select -p -->\"\n        )\n    return f\"\"\"\\\n#### Description\nUpdate dispenso to version {version}.\n\n[dispenso](https://github.com/facebookincubator/dispenso) is a high-performance \\\nC++ parallel programming library from Meta.\n\n###### Type(s)\n- [ ] bugfix\n- [x] enhancement\n- [ ] security fix\n\n###### Tested on\n{tested_on_section}\n\n###### Verification\n- [x] Followed [Commit Message Guidelines](https://trac.macports.org/wiki/CommitMessages)\n- [x] Squashed and minimized commits\n- [x] Checked that there aren't other open [pull requests](https://github.com/macports/macports-ports/pulls) for the same change\n- {test_check} Checked Portfile with `port lint --nitpick`\n- {test_check} Tried existing tests with `sudo port test`\n- {test_check} Tested with `sudo port -vst install`\n- {test_check} Checked that binaries work as expected\n- [x] Tested important variants (dispenso has no variants)\"\"\"\n\n\ndef pr_title(manager, version):\n    \"\"\"Generate the PR title for a given manager.\"\"\"\n    titles = {\n        \"conan\": f\"dispenso: add version {version}\",\n        \"vcpkg\": f\"[dispenso] Update to version {version}\",\n        \"homebrew\": f\"dispenso {version}\",\n        \"macports\": f\"dispenso: update to {version}\",\n    }\n    return titles.get(manager, f\"dispenso {version}\")\n\n\ndef pre_pr_checklist(manager, version, tests_ran):\n    \"\"\"Return items the user should manually verify before creating the PR.\"\"\"\n    checklists = {\n        \"homebrew\": [\n            \"Read contributing guidelines: https://github.com/Homebrew/homebrew-core/blob/HEAD/CONTRIBUTING.md\",\n            \"Run: HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source dispenso\",\n            \"Run: brew test dispenso\",\n            \"Run: brew audit --strict dispenso\",\n        ],\n        \"conan\": [\n            \"Sign the CLA if prompted on the PR\",\n            \"Run: conan create recipes/dispenso/all --version=\" + version,\n        ],\n        \"vcpkg\": [\n            \"Read maintainer guide: https://learn.microsoft.com/en-us/vcpkg/contributing/maintainer-guide\",\n            \"Run: vcpkg install dispenso --overlay-ports=ports/dispenso\",\n        ],\n        \"macports\": [\n            \"Fill in 'Tested on' section with output of: port version && sw_vers && xcode-select -p\",\n            \"Run: port lint --nitpick devel/dispenso\",\n            \"Run: sudo port -D devel/dispenso -vst install\",\n            \"Run: sudo port -D devel/dispenso test\",\n            \"Verify installed binaries work\",\n        ],\n    }\n\n    items = checklists.get(manager, [])\n    if tests_ran:\n        # Filter out \"Run:\" items that the script already tested\n        pass  # Keep all — user should still double-check\n    return items\n\n\n# ---------------------------------------------------------------------------\n# PR creation and guided flow\n# ---------------------------------------------------------------------------\n\n\ndef get_default_branch(upstream_repo):\n    \"\"\"Get the default branch of an upstream repo via gh API.\"\"\"\n    result = subprocess.run(\n        [\"gh\", \"api\", f\"repos/{upstream_repo}\", \"--jq\", \".default_branch\"],\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        return result.stdout.strip()\n    return \"master\"\n\n\ndef close_superseded_prs(upstream_repo, version, github_user, dry_run):\n    \"\"\"Close any open dispenso PRs by this user in the upstream repo.\"\"\"\n    result = subprocess.run(\n        [\n            \"gh\",\n            \"pr\",\n            \"list\",\n            \"--repo\",\n            upstream_repo,\n            \"--author\",\n            github_user,\n            \"--search\",\n            \"dispenso\",\n            \"--state\",\n            \"open\",\n            \"--json\",\n            \"number,title,url\",\n        ],\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode != 0 or not result.stdout.strip():\n        return\n\n    try:\n        prs = json.loads(result.stdout)\n    except json.JSONDecodeError:\n        return\n\n    for pr in prs:\n        title = pr.get(\"title\", \"\")\n        number = pr.get(\"number\")\n        if number is None:\n            continue\n        comment = (\n            f\"Superseded by version {version} update. Closing in favor of the new PR.\"\n        )\n        if dry_run:\n            print(f\"  [DRY RUN] Would close #{number}: {title}\")\n            continue\n\n        close_result = subprocess.run(\n            [\n                \"gh\",\n                \"pr\",\n                \"close\",\n                str(number),\n                \"--repo\",\n                upstream_repo,\n                \"--comment\",\n                comment,\n            ],\n            capture_output=True,\n            text=True,\n        )\n        if close_result.returncode == 0:\n            print(f\"  Closed #{number}: {title}\")\n        else:\n            print(\n                f\"  WARNING: Failed to close #{number}: {close_result.stderr.strip()}\"\n            )\n\n\ndef create_pr(upstream_repo, branch, title, body, github_user, dry_run):\n    \"\"\"Create a PR via gh CLI. Returns the PR URL or None.\"\"\"\n    if dry_run:\n        print(f\"  [DRY RUN] Would create PR: {title}\")\n        return None\n\n    base = get_default_branch(upstream_repo)\n\n    result = subprocess.run(\n        [\n            \"gh\",\n            \"pr\",\n            \"create\",\n            \"--repo\",\n            upstream_repo,\n            \"--head\",\n            f\"{github_user}:{branch}\",\n            \"--base\",\n            base,\n            \"--title\",\n            title,\n            \"--body\",\n            body,\n        ],\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        url = result.stdout.strip()\n        print(f\"  Created PR: {url}\")\n        return url\n\n    stderr = result.stderr.strip()\n    # If a PR already exists for this branch, extract its URL\n    if \"already exists\" in stderr:\n        print(f\"  PR already exists for branch {branch}\")\n        view_result = subprocess.run(\n            [\n                \"gh\",\n                \"pr\",\n                \"view\",\n                branch,\n                \"--repo\",\n                upstream_repo,\n                \"--json\",\n                \"url\",\n                \"--jq\",\n                \".url\",\n            ],\n            capture_output=True,\n            text=True,\n        )\n        if view_result.returncode == 0:\n            url = view_result.stdout.strip()\n            print(f\"  Existing PR: {url}\")\n            return url\n        return None\n\n    print(f\"  ERROR: Failed to create PR: {stderr}\")\n    return None\n\n\ndef create_prs_phase(results, args):\n    \"\"\"Create PRs for all successful managers. Returns dict of manager→URL.\"\"\"\n    if args.skip_push:\n        print(\"  --skip-push is set — cannot create PRs without pushing first.\")\n        return {}\n\n    gh_bin = shutil.which(\"gh\")\n    if not gh_bin:\n        print(\"  ERROR: gh CLI not found — install it to create PRs automatically.\")\n        print(\"  PR titles and bodies were printed above for manual creation.\")\n        return {}\n\n    print()\n    print(\"=\" * 60)\n    print(\"CREATING PRs\")\n    print(\"=\" * 60)\n\n    pr_urls = {}\n    for mgr, result in results.items():\n        if result.get(\"status\") not in (\"ok\",):\n            continue\n\n        upstream = UPSTREAM_REPOS[mgr]\n        branch = result.get(\"branch\", \"\")\n        title = result.get(\"pr_title\", \"\")\n        body = result.get(\"pr_body\", \"\")\n\n        if not branch or not title:\n            continue\n\n        print(f\"\\n--- {mgr} ---\")\n\n        # Close any superseded open PRs\n        close_superseded_prs(upstream, args.version, args.github_user, args.dry_run)\n\n        # Create the new PR\n        url = create_pr(upstream, branch, title, body, args.github_user, args.dry_run)\n        if url:\n            pr_urls[mgr] = url\n\n    if pr_urls:\n        print()\n        print(\"=\" * 60)\n        print(\"PR URLs\")\n        print(\"=\" * 60)\n        for mgr, url in pr_urls.items():\n            print(f\"  {mgr:12s}  {url}\")\n\n    return pr_urls\n\n\ndef post_pr_steps(pr_urls, version):\n    \"\"\"Guide the user through remaining manual post-PR steps.\"\"\"\n    print()\n    print(\"=\" * 60)\n    print(\"POST-PR STEPS\")\n    print(\"=\" * 60)\n\n    if \"conan\" in pr_urls:\n        print()\n        print(\"  Conan: If this is your first PR from this account, the CLA\")\n        print(\"  bot will comment on the PR. Sign it if prompted.\")\n        input(\"  Press Enter to continue ...\")\n\n    print()\n    print(\"  Monitor CI on each PR and respond to reviewer feedback.\")\n    print()\n    print(\"  All done!\")\n\n\ndef print_summary(results, github_user):\n    \"\"\"Print a summary of all operations.\"\"\"\n    print(\"=\" * 60)\n    print(\"SUMMARY\")\n    print(\"=\" * 60)\n\n    all_ok = True\n    for mgr, result in results.items():\n        status = result.get(\"status\", \"unknown\")\n        branch_url = result.get(\"branch_url\", \"\")\n        error = result.get(\"error\")\n\n        if status == \"ok\":\n            print(f\"  PASS  {mgr:12s}  {branch_url}\")\n        elif status == \"test_failed\":\n            print(f\"  FAIL  {mgr:12s}  Tests failed (branch not pushed)\")\n            all_ok = False\n        elif status == \"error\":\n            print(f\"  ERR   {mgr:12s}  {error}\")\n            all_ok = False\n        elif status == \"needs_macos\":\n            print(f\"  WARN  {mgr:12s}  Checksums OK, but full testing requires macOS\")\n            print(f\"        {'':12s}  {branch_url}\")\n        elif status == \"no_changes\":\n            print(f\"  SKIP  {mgr:12s}  Upstream already has this version\")\n        elif status == \"skipped\":\n            print(f\"  SKIP  {mgr:12s}  {result.get('reason', '')}\")\n        else:\n            print(f\"  ??    {mgr:12s}  {result}\")\n            all_ok = False\n\n    print()\n    if all_ok:\n        print(\"All managers succeeded. Review branches on GitHub, then create PRs.\")\n    else:\n        print(\"Some managers had issues. Fix and re-run for the failed ones.\")\n    print()\n\n    # Print PR body text for each successful manager\n    for mgr, result in results.items():\n        if result.get(\"status\") != \"ok\":\n            continue\n        version = result.get(\"version\", \"\")\n        tests_ran = result.get(\"tests_ran\", False)\n        body = result.get(\"pr_body\", \"\")\n        title = result.get(\"pr_title\", \"\")\n        if not body:\n            continue\n\n        print(\"=\" * 60)\n        print(f\"PR for {mgr}\")\n        print(\"=\" * 60)\n        print(f\"Title: {title}\")\n        print(f\"Branch: {result.get('branch_url', '')}\")\n\n        # Pre-PR checklist\n        checklist = pre_pr_checklist(mgr, version, tests_ran)\n        if checklist:\n            print()\n            print(\"  BEFORE CREATING PR, verify:\")\n            for i, item in enumerate(checklist, 1):\n                done = \"[x]\" if tests_ran and item.startswith(\"Run:\") else \"[ ]\"\n                print(f\"    {done} {item}\")\n            print()\n            print(\"  Check any unchecked boxes in the PR body after verifying.\")\n\n        print(\"-\" * 60)\n        print(body)\n        print(\"-\" * 60)\n        print()\n    print(\"Copy-paste the above PR bodies when creating PRs on GitHub.\")\n    print()\n\n\n# ---------------------------------------------------------------------------\n# Guided interactive flow\n# ---------------------------------------------------------------------------\n\n\ndef prompt_continue(message=\"Continue?\"):\n    \"\"\"Prompt user to continue, skip, or quit. Returns the chosen action.\"\"\"\n    response = input(f\"  {message} [Enter=yes / s=skip / q=quit] \").strip().lower()\n    if response in (\"\", \"y\", \"yes\"):\n        return \"continue\"\n    if response in (\"s\", \"skip\"):\n        return \"skip\"\n    if response in (\"q\", \"quit\"):\n        return \"quit\"\n    return \"continue\"\n\n\ndef _detect_default_branch(repo_dir):\n    \"\"\"Detect the default branch from local remote refs.\"\"\"\n    result = subprocess.run(\n        [\"git\", \"symbolic-ref\", \"refs/remotes/origin/HEAD\"],\n        cwd=repo_dir,\n        capture_output=True,\n        text=True,\n    )\n    if result.returncode == 0:\n        return result.stdout.strip().replace(\"refs/remotes/origin/\", \"\")\n    for candidate in [\"main\", \"master\"]:\n        r = subprocess.run(\n            [\"git\", \"show-ref\", \"--verify\", f\"refs/remotes/origin/{candidate}\"],\n            cwd=repo_dir,\n            capture_output=True,\n        )\n        if r.returncode == 0:\n            return candidate\n    return \"master\"\n\n\ndef _guided_run_updates(args, managers, hashes, tarball_path):\n    \"\"\"Run each manager's update handler, prompting before each.\n\n    Returns (results, aborted).  *aborted* is True if the user chose 'quit'.\n    \"\"\"\n    handlers = {\n        \"conan\": update_conan,\n        \"vcpkg\": update_vcpkg,\n        \"homebrew\": update_homebrew,\n        \"macports\": update_macports,\n    }\n    step_descriptions = {\n        \"vcpkg\": \"Update vcpkg port (version, SHA512, patches, version DB)\",\n        \"conan\": \"Update Conan recipe (conandata.yml, config.yml, issue)\",\n        \"homebrew\": \"Update Homebrew formula (URL, SHA256, build + test)\",\n        \"macports\": \"Update MacPorts Portfile (version, checksums, lint + install + test)\",\n    }\n\n    results = {}\n    for mgr in managers:\n        print()\n        print(\"=\" * 60)\n        print(f\"  {step_descriptions.get(mgr, mgr)}\")\n        if mgr in MACOS_ONLY_MANAGERS and platform.system() != \"Darwin\":\n            print(\"  (full testing requires macOS — will verify checksums only)\")\n        print(\"=\" * 60)\n\n        action = prompt_continue(f\"Proceed with {mgr}?\")\n        if action == \"quit\":\n            print(\"\\n  Quitting. Local commits (if any) are preserved.\")\n            return results, True\n        if action == \"skip\":\n            results[mgr] = {\"status\": \"skipped\", \"reason\": \"skipped by user\"}\n            continue\n\n        try:\n            results[mgr] = handlers[mgr](args, hashes, tarball_path)\n        except Exception as e:\n            print(f\"\\n  ERROR: {mgr} failed: {e}\")\n            results[mgr] = {\"status\": \"error\", \"error\": str(e)}\n\n        _print_manager_result(mgr, results[mgr])\n\n    return results, False\n\n\ndef _print_manager_result(mgr, result):\n    \"\"\"Print the outcome of a single manager update.\"\"\"\n    status = result.get(\"status\", \"unknown\")\n    messages = {\n        \"ok\": \"PASSED\",\n        \"no_changes\": \"SKIPPED — upstream already has this version\",\n        \"needs_macos\": \"checksums OK — re-run on macOS for full testing\",\n        \"test_failed\": \"TESTS FAILED — branch will not be pushed\",\n    }\n    if status in messages:\n        print(f\"\\n  {mgr}: {messages[status]}\")\n    elif status == \"error\":\n        print(f\"\\n  {mgr}: ERROR — {result.get('error', '')}\")\n\n\ndef _guided_push_branches(args, pushable):\n    \"\"\"Push branches to fork and print compare URLs.\n\n    Returns dict of successfully pushed managers.\n    \"\"\"\n    print()\n    print(\"=\" * 60)\n    print(\"  Pushing branches to fork\")\n    print(\"=\" * 60)\n\n    pushed = {}\n    for mgr, result in pushable.items():\n        repo_dir = os.path.join(args.repos_dir, REPO_DIRS[mgr])\n        branch = result.get(\"branch\", \"\")\n        if not branch:\n            continue\n        print(f\"\\n  {mgr}: pushing {branch} ...\")\n        run([\"git\", \"push\", \"-u\", \"fork\", branch, \"--force\"], cwd=repo_dir)\n        pushed[mgr] = result\n\n    print()\n    print(\"  All branches pushed. Review the proposed changes:\")\n    print()\n    for mgr, result in pushed.items():\n        upstream = UPSTREAM_REPOS[mgr]\n        repo_dir = os.path.join(args.repos_dir, REPO_DIRS[mgr])\n        default = _detect_default_branch(repo_dir)\n        branch = result.get(\"branch\", \"\")\n        repo_name = REPO_DIRS[mgr]\n        compare_url = (\n            f\"https://github.com/{upstream}/compare/\"\n            f\"{default}...{args.github_user}:{repo_name}:{branch}\"\n        )\n        print(f\"    {mgr:12s}  {compare_url}\")\n\n    return pushed\n\n\ndef _guided_create_prs(pushed, args):\n    \"\"\"Create PRs for successfully pushed managers via gh CLI.\n\n    Returns dict mapping manager name to PR URL.\n    \"\"\"\n    pr_urls = {}\n    for mgr, result in pushed.items():\n        if result.get(\"status\") != \"ok\":\n            continue\n        upstream = UPSTREAM_REPOS[mgr]\n        branch = result.get(\"branch\", \"\")\n        title = result.get(\"pr_title\", \"\")\n        body = result.get(\"pr_body\", \"\")\n        if not branch or not title:\n            continue\n\n        print(f\"\\n--- {mgr} ---\")\n        close_superseded_prs(upstream, args.version, args.github_user, False)\n        url = create_pr(upstream, branch, title, body, args.github_user, False)\n        if url:\n            pr_urls[mgr] = url\n\n    return pr_urls\n\n\ndef _guided_review_push_pr(args, results, pushable, tarball_path):\n    \"\"\"Review diffs, push branches, and create PRs.\n\n    Handles all user prompts for the post-update phase.\n    \"\"\"\n    version = args.version\n\n    # ---- Inspect diffs ----\n    print()\n    print(\"=\" * 60)\n    print(\"  Review changes before pushing\")\n    print(\"=\" * 60)\n    print()\n    print(\"  Inspect the diffs in each repo:\")\n    for mgr in pushable:\n        repo_dir = os.path.join(args.repos_dir, REPO_DIRS[mgr])\n        default = _detect_default_branch(repo_dir)\n        print(f\"    cd {repo_dir} && git diff origin/{default}...HEAD\")\n\n    action = prompt_continue(\"Diffs look good? Push to fork?\")\n    if action == \"quit\":\n        print(\"\\n  Quitting. Changes are committed locally in each repo.\")\n        _guided_cleanup(tarball_path)\n        return\n    if action == \"skip\":\n        print(\"\\n  Skipped push. Changes are committed locally.\")\n        print_summary(results, args.github_user)\n        _guided_cleanup(tarball_path)\n        return\n\n    # ---- Push ----\n    pushed = _guided_push_branches(args, pushable)\n\n    # ---- Create PRs ----\n    pr_urls = _guided_offer_pr_creation(args, pushed, results, tarball_path)\n    if pr_urls is None:\n        return\n\n    if pr_urls:\n        print()\n        print(\"=\" * 60)\n        print(\"  PR URLs\")\n        print(\"=\" * 60)\n        for mgr, url in pr_urls.items():\n            print(f\"    {mgr:12s}  {url}\")\n\n    post_pr_steps(pr_urls, version)\n\n    # ---- needs_macos reminder ----\n    needs_macos = [m for m, r in results.items() if r.get(\"status\") == \"needs_macos\"]\n    if needs_macos:\n        print()\n        print(\"=\" * 60)\n        print(\"  macOS required for full testing\")\n        print(\"=\" * 60)\n        mgr_list = \",\".join(needs_macos)\n        print(\"\\n  Re-run on macOS to complete testing and create PRs:\")\n        print(\n            f\"    python3 {sys.argv[0]} --version {version}\"\n            f\" --managers {mgr_list} --guided\"\n        )\n\n    _guided_cleanup(tarball_path)\n    print()\n    print(\"  Release update complete!\")\n\n\ndef _guided_offer_pr_creation(args, pushed, results, tarball_path):\n    \"\"\"Prompt to create PRs via gh CLI.\n\n    Returns pr_urls dict, or None if the user skipped/quit or gh is missing.\n    \"\"\"\n    print()\n    print(\"=\" * 60)\n    print(\"  Create pull requests\")\n    print(\"=\" * 60)\n\n    gh_bin = shutil.which(\"gh\")\n    if not gh_bin:\n        print()\n        print(\"  gh CLI not found. Install it to create PRs automatically.\")\n        print(\"  PR titles and bodies are printed below for manual creation.\")\n        print_summary(results, args.github_user)\n        _guided_cleanup(tarball_path)\n        return None\n\n    action = prompt_continue(\"Create PRs via gh CLI?\")\n    if action in (\"skip\", \"quit\"):\n        print(\"\\n  Branches are pushed. Create PRs manually if needed.\")\n        print_summary(results, args.github_user)\n        _guided_cleanup(tarball_path)\n        return None\n\n    return _guided_create_prs(pushed, args)\n\n\ndef guided_flow(args):\n    \"\"\"Run the complete release update flow interactively.\n\n    Walks through every step, prompts before each action, and creates PRs\n    at the end. Replaces the need for a separate checklist document.\n    \"\"\"\n    version = args.version\n    managers = args.managers\n\n    print()\n    print(\"=\" * 60)\n    print(f\"  dispenso {version} — guided release update\")\n    print(\"=\" * 60)\n    print()\n    print(\"  Managers: \" + \", \".join(managers))\n    if args.dry_run:\n        print(\"  Mode: DRY RUN (no files will be modified)\")\n    if args.skip_test:\n        print(\"  Mode: SKIP TESTS\")\n    print()\n    print(\"  At each step you can press Enter to continue,\")\n    print(\"  's' to skip, or 'q' to quit.\")\n    print()\n\n    # ---- Download tarball ----\n    print(\"-\" * 60)\n    print(\"  Downloading release tarball ...\")\n    print(\"-\" * 60)\n    tarball_path, hashes = download_and_hash(version)\n\n    # ---- Update each manager (no push) ----\n    original_skip_push = args.skip_push\n    args.skip_push = True\n    results, aborted = _guided_run_updates(args, managers, hashes, tarball_path)\n    args.skip_push = original_skip_push\n\n    if aborted:\n        _guided_cleanup(tarball_path)\n        return\n\n    pushable = {\n        m: r for m, r in results.items() if r.get(\"status\") in (\"ok\", \"needs_macos\")\n    }\n\n    if not pushable:\n        print(\"\\n  No managers succeeded. Fix issues and re-run.\")\n        _guided_cleanup(tarball_path)\n        return\n\n    if args.dry_run:\n        print(\"\\n  Dry run complete. Re-run without --dry-run to apply changes.\")\n        _guided_cleanup(tarball_path)\n        return\n\n    _guided_review_push_pr(args, results, pushable, tarball_path)\n\n\ndef _guided_cleanup(tarball_path):\n    \"\"\"Clean up the downloaded tarball.\"\"\"\n    if os.path.exists(tarball_path):\n        os.unlink(tarball_path)\n        print(f\"\\n  Cleaned up {tarball_path}\")\n\n\ndef main():\n    args = parse_args()\n\n    if args.guided:\n        guided_flow(args)\n        return\n\n    print(f\"Updating dispenso to version {args.version}\")\n    if args.dry_run:\n        print(\"*** DRY RUN MODE — no files will be modified ***\")\n    if args.skip_test:\n        print(\"*** SKIP TEST MODE — no local verification ***\")\n    if args.skip_push:\n        print(\"*** SKIP PUSH MODE — commit and test only ***\")\n    if args.create_prs:\n        print(\"*** CREATE PRS MODE — will create PRs after push ***\")\n    print()\n\n    tarball_path, hashes = download_and_hash(args.version)\n\n    handlers = {\n        \"conan\": update_conan,\n        \"vcpkg\": update_vcpkg,\n        \"homebrew\": update_homebrew,\n        \"macports\": update_macports,\n    }\n\n    results = {}\n    for mgr in args.managers:\n        try:\n            results[mgr] = handlers[mgr](args, hashes, tarball_path)\n        except Exception as e:\n            print(f\"  ERROR: {mgr} failed: {e}\")\n            results[mgr] = {\"status\": \"error\", \"error\": str(e)}\n            print()\n\n    print_summary(results, args.github_user)\n\n    # Create PRs if requested\n    if args.create_prs:\n        pr_urls = create_prs_phase(results, args)\n        if pr_urls:\n            post_pr_steps(pr_urls, args.version)\n\n    # Clean up tarball\n    if os.path.exists(tarball_path):\n        os.unlink(tarball_path)\n        print(f\"Cleaned up {tarball_path}\")\n\n    # Check if any macOS-only managers need full testing\n    needs_macos = [\n        mgr for mgr, result in results.items() if result.get(\"status\") == \"needs_macos\"\n    ]\n    if needs_macos:\n        print()\n        print(\"=\" * 60)\n        print(\"ERROR: Full testing requires macOS\")\n        print(\"=\" * 60)\n        print(\"  The following managers were updated and checksums verified,\")\n        print(\"  but full testing (lint, install, audit) requires macOS:\")\n        for mgr in needs_macos:\n            print(f\"    - {mgr}\")\n        print()\n        print(\"  Please re-run on macOS to complete testing:\")\n        mgr_list = \",\".join(needs_macos)\n        print(\n            f\"    python3 {sys.argv[0]} --version {args.version} --managers {mgr_list}\"\n        )\n        sys.exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "tests/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.18)\n\n### TODO(bbudge): Set up testing with github actions\n# Ideally these tests are all run in (Release, Debug) X (N/A, TSAN, ASAN, -fno-exceptions)\n###\n\n# Try system-installed GTest first, fall back to FetchContent from GitHub.\nfind_package(GTest QUIET)\nif(GTest_FOUND)\n  message(STATUS \"Found system GoogleTest\")\n  # System GTest provides namespaced targets (GTest::gmock_main); create\n  # non-namespaced aliases so existing target_link_libraries calls work.\n  if(NOT TARGET gmock_main AND TARGET GTest::gmock_main)\n    add_library(gmock_main ALIAS GTest::gmock_main)\n  endif()\nelse()\n  message(STATUS \"System GoogleTest not found, fetching from GitHub...\")\n  include(FetchContent)\n  FetchContent_Declare(\n    GoogleTest\n    GIT_REPOSITORY https://github.com/google/googletest.git\n    GIT_TAG        release-1.12.1\n  )\n  # For Windows, Prevent overriding the parent project's compiler/linker settings\n  set(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\n  set(INSTALL_GTEST OFF CACHE BOOL \"\" FORCE)\n  FetchContent_MakeAvailable(GoogleTest)\nendif()\ninclude(GoogleTest)\n\nmacro(package_add_test TEST_NAME LABEL TEST_FILE)\n    add_executable(${TEST_NAME} ${TEST_FILE})\n    target_compile_options(${TEST_NAME} PRIVATE\n      $<$<CXX_COMPILER_ID:MSVC>:/W3 /WX>\n      # GCC false positives: stringop-overflow through deeply inlined atomics\n      # (seen with GCC 13 on Linux, GCC 14 on macOS ARM64), and\n      # maybe-uninitialized through inlined try_pop + gtest macros (GCC 13).\n      $<$<CXX_COMPILER_ID:GNU>:-Wno-stringop-overflow -Wno-maybe-uninitialized>\n      $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion -Werror>\n      )\n    target_link_libraries(${TEST_NAME} gmock_main dispenso)\n    gtest_discover_tests(${TEST_NAME}\n      WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}\n      PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}\"\n      LABELS \"${LABEL}\"\n      DISCOVERY_MODE PRE_TEST)\n    set_target_properties(${TEST_NAME} PROPERTIES FOLDER tests)\nendmacro()\n\nfile(GLOB TEST_FILES CONFIGURE_DEPENDS \"*test.cpp\")\n\n#TODO(elliotsegal, bbudge): Help add the shared_pool_test for CMake\nLIST(REMOVE_ITEM TEST_FILES\n  ${CMAKE_CURRENT_SOURCE_DIR}/shared_pool_test.cpp)\n\n# Filter out these tests specifically because they are inherently flaky because they rely on OS behaviors that are not\n# guaranteed, and only really useful for manual runs when making changes to the related functionality.  Note that\n# possibly an even better test for both priority and timed_task behavior is to use the timed_task_benchmark.\nLIST(REMOVE_ITEM TEST_FILES\n  ${CMAKE_CURRENT_SOURCE_DIR}/priority_test.cpp\n  ${CMAKE_CURRENT_SOURCE_DIR}/timed_task_test.cpp)\n\nforeach(TEST_FILE ${TEST_FILES})\n  set(TEST_NAME)\n  get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n  package_add_test(${TEST_NAME} unittest ${TEST_FILE})\nendforeach()\n\nSET(FLAKY_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/priority_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timed_task_test.cpp)\n\nforeach(TEST_FILE ${FLAKY_TEST_FILES})\n  set(TEST_NAME)\n  get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n  package_add_test(${TEST_NAME} flaky ${TEST_FILE})\nendforeach()\n\nif(DISPENSO_BUILD_FAST_MATH)\n  add_subdirectory(fast_math)\nendif()\n"
  },
  {
    "path": "tests/async_request_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <thread>\n\n#include <dispenso/async_request.h>\n\n#include <gtest/gtest.h>\n\nTEST(AsyncRequest, SequentialAsExpected) {\n  dispenso::AsyncRequest<int> req;\n\n  EXPECT_FALSE(req.updateRequested());\n  EXPECT_FALSE(req.tryEmplaceUpdate(5));\n  EXPECT_FALSE(req.getUpdate());\n\n  req.requestUpdate();\n\n  EXPECT_TRUE(req.updateRequested());\n\n  EXPECT_FALSE(req.getUpdate());\n\n  EXPECT_TRUE(req.tryEmplaceUpdate(0));\n\n  auto result = req.getUpdate();\n  EXPECT_TRUE(result);\n  EXPECT_EQ(0, result.value());\n}\n\nTEST(AsyncRequest, AsyncAsExpected) {\n  dispenso::AsyncRequest<int> req;\n  std::atomic<bool> running(true);\n  std::thread t([&req, &running]() {\n    int next = 0;\n    while (running.load(std::memory_order_relaxed)) {\n      if (req.updateRequested()) {\n        req.tryEmplaceUpdate(next++);\n      }\n    }\n  });\n\n  int sum = 0;\n  int sumExpected = 0;\n  for (int i = 0; i < 5000; ++i) {\n    sumExpected += i;\n\n    req.requestUpdate();\n    while (true) {\n      auto result = req.getUpdate();\n      if (result.has_value()) {\n        sum += result.value();\n        break;\n      }\n    }\n  }\n\n  running.store(false, std::memory_order_release);\n  t.join();\n\n  EXPECT_EQ(sum, sumExpected);\n}\n"
  },
  {
    "path": "tests/chunked_for_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <list>\n#include <vector>\n\n#include <dispenso/concurrent_vector.h>\n#include <dispenso/parallel_for.h>\n#include <gtest/gtest.h>\n\nTEST(ChunkedFor, SimpleLoop) {\n  int w = 1024;\n  int h = 1024;\n  std::vector<int> image(static_cast<size_t>(w * h), 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, h, 8), [w, &image, &sum](int ystart, int yend) {\n        EXPECT_EQ(yend - ystart, 8);\n        int64_t s = 0;\n        for (int y = ystart; y < yend; ++y) {\n          int* row = image.data() + y * w;\n          for (int i = 0; i < w; ++i) {\n            s += row[i];\n          }\n        }\n        sum.fetch_add(s, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(ChunkedFor, ShouldNotInvokeIfEmptyRange) {\n  int* myNullPtr = nullptr;\n\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, 0, dispenso::ParForChunking::kAuto),\n      [myNullPtr](int s, int e) { *myNullPtr = s + e; });\n\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, 0, dispenso::ParForChunking::kStatic),\n      [myNullPtr](int s, int e) { *myNullPtr = s + e; });\n}\n\nTEST(ChunkedFor, SimpleLoopStatic) {\n  int w = 1024;\n  int h = 1024;\n  std::vector<int> image(static_cast<size_t>(w * h), 7);\n\n  std::atomic<int64_t> sum(0);\n  std::atomic<int> numCalls(0);\n\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, h, dispenso::ParForChunking::kStatic),\n      [w, &image, &sum, &numCalls](int ystart, int yend) {\n        numCalls.fetch_add(1, std::memory_order_relaxed);\n        int64_t s = 0;\n        for (int y = ystart; y < yend; ++y) {\n          int* row = image.data() + y * w;\n          for (int i = 0; i < w; ++i) {\n            s += row[i];\n          }\n        }\n        sum.fetch_add(s, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_LE(\n      numCalls.load(std::memory_order_relaxed),\n      static_cast<int>(std::thread::hardware_concurrency()));\n}\n\nTEST(ChunkedFor, SimpleLoopAuto) {\n  int w = 1024;\n  int h = 1024;\n  std::vector<int> image(static_cast<size_t>(w * h), 7);\n\n  std::atomic<int64_t> sum(0);\n  std::atomic<int> numCalls(0);\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, h, dispenso::ParForChunking::kAuto),\n      [w, &image, &sum, &numCalls](int ystart, int yend) {\n        numCalls.fetch_add(1, std::memory_order_relaxed);\n        int64_t s = 0;\n        for (int y = ystart; y < yend; ++y) {\n          int* row = image.data() + y * w;\n          for (int i = 0; i < w; ++i) {\n            s += row[i];\n          }\n        }\n        sum.fetch_add(s, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_GT(\n      numCalls.load(std::memory_order_relaxed),\n      static_cast<int>(std::thread::hardware_concurrency()));\n  EXPECT_LE(numCalls.load(std::memory_order_relaxed), 1024);\n}\n\ntemplate <typename StateContainer>\nvoid loopWithStateImpl() {\n  int w = 1024;\n  int h = 1024;\n  std::vector<int> image(static_cast<size_t>(w * h), 7);\n\n  StateContainer state;\n  dispenso::parallel_for(\n      state,\n      []() { return int64_t{0}; },\n      dispenso::makeChunkedRange(0, h, 16),\n      [w, &image](int64_t& sum, int ystart, int yend) {\n        EXPECT_EQ(yend - ystart, 16);\n        int64_t s = 0;\n        for (int y = ystart; y < yend; ++y) {\n          int* row = image.data() + y * w;\n          for (int i = 0; i < w; ++i) {\n            s += row[i];\n          }\n        }\n        sum += s;\n      });\n\n  int64_t sum = 0;\n  for (int64_t s : state) {\n    sum += s;\n  }\n\n  EXPECT_EQ(sum, w * h * 7);\n}\n\nTEST(ChunkedFor, LoopWithDequeState) {\n  loopWithStateImpl<std::deque<int64_t>>();\n}\nTEST(ChunkedFor, LoopWithVectorState) {\n  loopWithStateImpl<std::vector<int64_t>>();\n}\nTEST(ChunkedFor, LoopWithListState) {\n  loopWithStateImpl<std::list<int64_t>>();\n}\n\nTEST(ChunkedFor, SimpleLoopSmallRangeAtLargeValues) {\n  std::atomic<uint64_t> numCalls(0);\n\n  dispenso::ThreadPool pool(6);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::parallel_for(\n      tasks,\n      dispenso::makeChunkedRange(\n          std::numeric_limits<uint64_t>::max() / 2 - 100,\n          std::numeric_limits<uint64_t>::max() / 2 + 1000,\n          dispenso::ParForChunking::kAuto),\n      [&numCalls](auto ystart, auto yend) {\n        numCalls.fetch_add(yend - ystart, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(numCalls.load(std::memory_order_relaxed), 1100);\n}\n\nTEST(ChunkedFor, SimpleLoopSmallRange) {\n  std::atomic<int> numCalls(0);\n\n  dispenso::ThreadPool pool(6);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::parallel_for(\n      tasks,\n      dispenso::makeChunkedRange(\n          std::numeric_limits<int16_t>::min(),\n          std::numeric_limits<int16_t>::max(),\n          dispenso::ParForChunking::kAuto),\n      [&numCalls](auto ystart, auto yend) {\n        numCalls.fetch_add(yend - ystart, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(numCalls.load(std::memory_order_relaxed), (1 << 16) - 1);\n}\n\nTEST(ChunkedFor, LoopSmallRangeWithState) {\n  std::atomic<int> numCalls(0);\n\n  dispenso::ThreadPool pool(6);\n  dispenso::TaskSet tasks(pool);\n\n  std::vector<int> state;\n\n  dispenso::parallel_for(\n      tasks,\n      state,\n      []() { return 0; },\n      dispenso::makeChunkedRange(\n          std::numeric_limits<int16_t>::min(),\n          std::numeric_limits<int16_t>::max(),\n          dispenso::ParForChunking::kAuto),\n      [&numCalls](auto& s, auto ystart, auto yend) {\n        numCalls.fetch_add(yend - ystart, std::memory_order_relaxed);\n        s += (yend - ystart);\n      });\n\n  EXPECT_EQ(numCalls.load(std::memory_order_relaxed), (1 << 16) - 1);\n  int total = 0;\n  for (int s : state) {\n    total += s;\n  }\n  EXPECT_EQ(total, (1 << 16) - 1);\n}\n\nTEST(ChunkedFor, SimpleLoopSmallRangeExternalWait) {\n  std::atomic<int> numCalls(0);\n\n  dispenso::ThreadPool pool(6);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  dispenso::parallel_for(\n      tasks,\n      dispenso::makeChunkedRange(\n          std::numeric_limits<int16_t>::min(),\n          std::numeric_limits<int16_t>::max(),\n          dispenso::ParForChunking::kAuto),\n      [&numCalls](auto ystart, auto yend) {\n        numCalls.fetch_add(yend - ystart, std::memory_order_relaxed);\n      },\n      options);\n  tasks.wait();\n\n  EXPECT_EQ(numCalls.load(std::memory_order_relaxed), (1 << 16) - 1);\n}\n\nTEST(ChunkedFor, LoopSmallRangeWithStateWithExternalWait) {\n  std::atomic<int> numCalls(0);\n\n  dispenso::ThreadPool pool(6);\n  dispenso::TaskSet tasks(pool);\n\n  std::vector<int> state;\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  dispenso::parallel_for(\n      tasks,\n      state,\n      []() { return 0; },\n      dispenso::makeChunkedRange(\n          std::numeric_limits<int16_t>::min(),\n          std::numeric_limits<int16_t>::max(),\n          dispenso::ParForChunking::kAuto),\n      [&numCalls](auto& s, auto ystart, auto yend) {\n        numCalls.fetch_add(yend - ystart, std::memory_order_relaxed);\n        s += (yend - ystart);\n      },\n      options);\n\n  tasks.wait();\n\n  EXPECT_EQ(numCalls.load(std::memory_order_relaxed), (1 << 16) - 1);\n  int total = 0;\n  for (int s : state) {\n    total += s;\n  }\n  EXPECT_EQ(total, (1 << 16) - 1);\n}\n\nstatic void minChunkSize(dispenso::ParForChunking choice, int start, int end, int minSize) {\n  dispenso::ConcurrentVector<std::pair<int, int>> ranges;\n\n  dispenso::ThreadPool pool(16);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::ParForOptions options;\n  options.minItemsPerChunk = minSize;\n\n  dispenso::parallel_for(\n      tasks,\n      dispenso::makeChunkedRange(start, end, choice),\n      [&ranges](int ystart, int yend) { ranges.push_back({ystart, yend}); },\n      options);\n\n  EXPECT_GE(ranges.size(), 1);\n\n  for (auto& r : ranges) {\n    if (r.second != end) {\n      EXPECT_LE(minSize, r.second - r.first);\n    }\n  }\n}\n\nTEST(ChunkedFor, MinChunkSizeLoopAuto) {\n  minChunkSize(dispenso::ParForChunking::kAuto, 0, 1000000, 200);\n  minChunkSize(dispenso::ParForChunking::kAuto, 0, 100, 200);\n  minChunkSize(dispenso::ParForChunking::kAuto, 10000, 10020, 200);\n  minChunkSize(dispenso::ParForChunking::kAuto, 1000000, 10000000, 20000);\n  minChunkSize(dispenso::ParForChunking::kAuto, -10000000, -1000000, 20000);\n}\n\nTEST(ChunkedFor, MinChunkSizeLoopStatic) {\n  minChunkSize(dispenso::ParForChunking::kStatic, 0, 1000000, 200);\n  minChunkSize(dispenso::ParForChunking::kStatic, 0, 100, 200);\n  minChunkSize(dispenso::ParForChunking::kStatic, 10000, 10020, 200);\n  minChunkSize(dispenso::ParForChunking::kStatic, 1000000, 10000000, 20000);\n  minChunkSize(dispenso::ParForChunking::kStatic, -10000000, -1000000, 20000);\n}\n\ntemplate <typename StateContainer>\nvoid loopWithStateImplReuseState() {\n  int w = 1024;\n  int h = 1024;\n  std::vector<int> image(static_cast<size_t>(w * h), 7);\n\n  StateContainer state;\n\n  dispenso::ParForOptions options;\n  options.reuseExistingState = true;\n\n  for (size_t i = 0; i < 3; ++i) {\n    dispenso::parallel_for(\n        state,\n        []() { return int64_t{0}; },\n        dispenso::makeChunkedRange(0, h, 16),\n        [w, &image](int64_t& sum, int ystart, int yend) {\n          EXPECT_EQ(yend - ystart, 16);\n          int64_t s = 0;\n          for (int y = ystart; y < yend; ++y) {\n            int* row = image.data() + y * w;\n            for (int i = 0; i < w; ++i) {\n              s += row[i];\n            }\n          }\n          sum += s;\n        },\n        options);\n  }\n\n  int64_t sum = 0;\n  for (int64_t s : state) {\n    sum += s;\n  }\n\n  EXPECT_EQ(sum, 3 * w * h * 7);\n}\n\nTEST(ChunkedFor, LoopWithDequeStateReuse) {\n  loopWithStateImplReuseState<std::deque<int64_t>>();\n}\nTEST(ChunkedFor, LoopWithVectorStateReuse) {\n  loopWithStateImplReuseState<std::vector<int64_t>>();\n}\nTEST(ChunkedFor, LoopWithListStateReuse) {\n  loopWithStateImplReuseState<std::list<int64_t>>();\n}\n"
  },
  {
    "path": "tests/completion_event_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <deque>\n#include <thread>\n\n#include <dispenso/completion_event.h>\n\n#include <gtest/gtest.h>\n\nTEST(CompletionEvent, NotifyBeforeWait) {\n  dispenso::CompletionEvent event;\n\n  event.notify();\n  // Should immediately return;\n  event.wait();\n}\n\nTEST(CompletionEvent, NotifyBeforeWaitFor) {\n  dispenso::CompletionEvent event;\n\n  event.notify();\n  // Should immediately return;\n  EXPECT_TRUE(event.waitFor(std::chrono::microseconds(1)));\n}\n\n// In an ideal world, we could expect the following test to loop 10 times or so.  In reality, we\n// can't make such guarantees when it comes to sleep() and wait() functions.  For instance, on Linux\n// with 64 mostly-idle cores, 100 out of 100 runs of this test resulted in looping between 8 and 12\n// times, even under TSAN.  On Mac with 4 less-idle cores, the test would pass about 90 out of 100.\n// Inflating the interval to 7 to 13 passed 98 out of 100.  In the end, we cannot really count on\n// any concrete number of times through the loop (think TSAN, think loaded machine, etc...), and so\n// we simply let this test fall back to \"will this time out?\".\nTEST(CompletionEvent, WaitForSomeTime) {\n  dispenso::CompletionEvent event;\n\n  std::thread t([&event]() {\n    std::this_thread::sleep_for(std::chrono::milliseconds(20));\n    event.notify();\n  });\n\n  while (true) {\n    if (event.waitFor(std::chrono::milliseconds(2))) {\n      break;\n    }\n  }\n\n  t.join();\n}\n\nTEST(CompletionEvent, WaitForSomeTimeWithReset) {\n  dispenso::CompletionEvent event;\n  std::atomic<bool> barrier(0);\n\n  std::thread t([&event, &barrier]() {\n    std::this_thread::sleep_for(std::chrono::milliseconds(20));\n    event.notify();\n\n    while (!barrier.load(std::memory_order_acquire)) {\n    }\n    std::this_thread::sleep_for(std::chrono::milliseconds(20));\n    event.notify();\n  });\n\n  while (!(event.waitFor(std::chrono::milliseconds(2)))) {\n  }\n\n  EXPECT_TRUE(event.waitFor(std::chrono::microseconds(1))) << \"This should immediately return true\";\n\n  // No threads waiting, nor notifying, so we can reset.\n  event.reset();\n\n  // Trigger the barrier so that the event can be notified.\n  barrier.store(1, std::memory_order_release);\n\n  while (true) {\n    if (event.waitFor(std::chrono::milliseconds(2))) {\n      break;\n    }\n  }\n\n  t.join();\n}\n\nTEST(CompletionEvent, EffectiveBarrier) {\n  dispenso::CompletionEvent event;\n\n  std::deque<std::thread> threads;\n\n  std::atomic<int> count(0);\n\n  constexpr int kThreads = 4;\n\n  for (size_t i = 0; i < kThreads; ++i) {\n    threads.emplace_back([&event, &count]() {\n      count.fetch_sub(1, std::memory_order_relaxed);\n      event.wait();\n      count.fetch_add(2, std::memory_order_relaxed);\n    });\n  }\n\n  while (count.load(std::memory_order_acquire) > -kThreads) {\n  }\n\n  // Take a long rest in this thread.  This gives us a chance to ensure that the event cannot\n  // spurious wake, and begin modifying \"count\".\n  std::this_thread::sleep_for(std::chrono::milliseconds(20));\n\n  EXPECT_EQ(-kThreads, count.load(std::memory_order_acquire));\n\n  event.notify();\n\n  for (auto& t : threads) {\n    t.join();\n  }\n\n  EXPECT_EQ(kThreads, count.load(std::memory_order_acquire));\n}\n"
  },
  {
    "path": "tests/concurrent_object_arena_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/concurrent_object_arena.h>\n#include <dispenso/task_set.h>\n\n#include <gtest/gtest.h>\n\nTEST(ConcurrentObjectArena, ParallelGrowBy) {\n  constexpr size_t numTasks = 20;\n  constexpr size_t numLoops = 100;\n  constexpr size_t delta = 7;\n  constexpr size_t bufSize = 16;\n\n  dispenso::ConcurrentObjectArena<size_t> arena(bufSize);\n\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n  for (size_t ti = 0; ti < numTasks; ++ti) {\n    taskSet.schedule([=, &arena]() {\n      for (size_t i = 0; i < numLoops; i++) {\n        const size_t p = arena.grow_by(delta);\n        for (size_t j = 0; j < delta; j++) {\n          arena[p + j] = ti * numLoops * delta + i;\n        }\n      }\n    });\n  }\n  taskSet.wait();\n\n  EXPECT_EQ(delta * numLoops * numTasks, arena.size());\n  EXPECT_EQ(arena.capacity() / arena.numBuffers(), arena.getBufferSize(0));\n\n  size_t totalSize = 0;\n  for (size_t i = 0; i < arena.numBuffers(); ++i) {\n    totalSize += arena.getBufferSize(i);\n  }\n  EXPECT_EQ(totalSize, arena.size());\n\n  for (size_t i = 0; i < numLoops * numTasks; i++) {\n    const size_t firstElement = arena[i * delta];\n    for (size_t j = 1; j < delta; j++) {\n      EXPECT_EQ(arena[i * delta + j], firstElement);\n    }\n  }\n}\n\nTEST(ConcurrentObjectArena, ObjectsConstuction) {\n  constexpr size_t defaultValue = 17;\n  constexpr size_t bufSize = 16;\n  constexpr size_t smallGrow = bufSize / 3;\n  constexpr size_t bigGrow = bufSize * 3;\n\n  struct TestData {\n    TestData() : value(defaultValue) {}\n    size_t value;\n  };\n\n  dispenso::ConcurrentObjectArena<TestData>* arena =\n      new dispenso::ConcurrentObjectArena<TestData>(bufSize);\n\n  arena->grow_by(smallGrow);\n  arena->grow_by(bigGrow);\n\n  const size_t num = arena->size();\n  for (size_t i = 0; i < num; ++i) {\n    EXPECT_EQ((*arena)[i].value, defaultValue);\n  }\n\n  dispenso::ConcurrentObjectArena<TestData> copyArena(*arena);\n\n  dispenso::ConcurrentObjectArena<TestData> copyAssignmentArena(bufSize / 2);\n  copyAssignmentArena = *arena;\n\n  EXPECT_EQ(copyArena.size(), arena->size());\n  EXPECT_EQ(copyAssignmentArena.size(), arena->size());\n\n  const size_t numBuffers = arena->numBuffers();\n  std::vector<const TestData*> bufferPtrs(numBuffers);\n  for (size_t i = 0; i < numBuffers; ++i) {\n    bufferPtrs[i] = arena->getBuffer(i);\n  }\n\n  dispenso::ConcurrentObjectArena<TestData> moveArena(std::move(*arena));\n\n  EXPECT_EQ(arena->size(), 0);\n  EXPECT_EQ(arena->numBuffers(), 0);\n  EXPECT_EQ(arena->capacity(), 0);\n\n  delete arena;\n\n  EXPECT_EQ(copyArena.numBuffers(), numBuffers);\n  EXPECT_EQ(copyAssignmentArena.numBuffers(), numBuffers);\n\n  for (size_t i = 0; i < num; ++i) {\n    EXPECT_EQ(copyArena[i].value, defaultValue);\n    EXPECT_EQ(copyAssignmentArena[i].value, defaultValue);\n  }\n\n  for (size_t i = 0; i < numBuffers; ++i) {\n    EXPECT_NE(copyArena.getBuffer(i), bufferPtrs[i]);\n    EXPECT_NE(copyAssignmentArena.getBuffer(i), bufferPtrs[i]);\n    EXPECT_EQ(moveArena.getBuffer(i), bufferPtrs[i]);\n  }\n}\n\nTEST(ConcurrentObjectArena, BufferSizeRounding) {\n  // Test that non-power-of-2 buffer sizes are rounded up\n  // minBuffSize = 10 should round up to 16 (next power of 2)\n  dispenso::ConcurrentObjectArena<int> arena(10);\n\n  arena.grow_by(20);\n\n  // Capacity should be a multiple of 16 (the rounded buffer size)\n  EXPECT_EQ(arena.capacity() % 16, 0u);\n\n  // Buffer size should be 16\n  EXPECT_EQ(arena.capacity() / arena.numBuffers(), 16u);\n}\n\nTEST(ConcurrentObjectArena, ExactPowerOfTwoBufferSize) {\n  // Test that exact power-of-2 buffer sizes are preserved\n  dispenso::ConcurrentObjectArena<int> arena(32);\n\n  arena.grow_by(100);\n\n  // Buffer size should be exactly 32\n  EXPECT_EQ(arena.capacity() / arena.numBuffers(), 32u);\n}\n\nTEST(ConcurrentObjectArena, MoveAssignment) {\n  dispenso::ConcurrentObjectArena<int> arena1(16);\n  dispenso::ConcurrentObjectArena<int> arena2(8);\n\n  arena1.grow_by(50);\n  for (size_t i = 0; i < 50; ++i) {\n    arena1[i] = static_cast<int>(i * 2);\n  }\n\n  arena2.grow_by(10);\n  for (size_t i = 0; i < 10; ++i) {\n    arena2[i] = static_cast<int>(i * 3);\n  }\n\n  size_t arena1Size = arena1.size();\n  size_t arena1NumBuffers = arena1.numBuffers();\n  size_t arena2Size = arena2.size();\n\n  // Move assign arena1 to arena2 (uses swap internally)\n  arena2 = std::move(arena1);\n\n  // arena2 should now have arena1's contents\n  EXPECT_EQ(arena2.size(), arena1Size);\n  EXPECT_EQ(arena2.numBuffers(), arena1NumBuffers);\n  for (size_t i = 0; i < arena1Size; ++i) {\n    EXPECT_EQ(arena2[i], static_cast<int>(i * 2));\n  }\n\n  // arena1 now has arena2's old contents (swap behavior)\n  EXPECT_EQ(arena1.size(), arena2Size);\n}\n\nTEST(ConcurrentObjectArena, SwapFunction) {\n  dispenso::ConcurrentObjectArena<int> arena1(16);\n  dispenso::ConcurrentObjectArena<int> arena2(32);\n\n  arena1.grow_by(20);\n  for (size_t i = 0; i < 20; ++i) {\n    arena1[i] = 100;\n  }\n\n  arena2.grow_by(40);\n  for (size_t i = 0; i < 40; ++i) {\n    arena2[i] = 200;\n  }\n\n  size_t size1 = arena1.size();\n  size_t size2 = arena2.size();\n\n  swap(arena1, arena2);\n\n  EXPECT_EQ(arena1.size(), size2);\n  EXPECT_EQ(arena2.size(), size1);\n\n  for (size_t i = 0; i < arena1.size(); ++i) {\n    EXPECT_EQ(arena1[i], 200);\n  }\n  for (size_t i = 0; i < arena2.size(); ++i) {\n    EXPECT_EQ(arena2[i], 100);\n  }\n}\n\nTEST(ConcurrentObjectArena, ConstAccess) {\n  dispenso::ConcurrentObjectArena<int> arena(16);\n  arena.grow_by(10);\n  for (size_t i = 0; i < 10; ++i) {\n    arena[i] = static_cast<int>(i);\n  }\n\n  const dispenso::ConcurrentObjectArena<int>& constArena = arena;\n\n  // Test const operator[]\n  for (size_t i = 0; i < 10; ++i) {\n    EXPECT_EQ(constArena[i], static_cast<int>(i));\n  }\n\n  // Test const getBuffer\n  const int* buf = constArena.getBuffer(0);\n  EXPECT_NE(buf, nullptr);\n\n  // Test const size, capacity, numBuffers\n  EXPECT_EQ(constArena.size(), 10u);\n  EXPECT_GE(constArena.capacity(), 10u);\n  EXPECT_GE(constArena.numBuffers(), 1u);\n\n  // Test const getBufferSize\n  EXPECT_GT(constArena.getBufferSize(0), 0u);\n}\n\nTEST(ConcurrentObjectArena, DifferentIndexType) {\n  // Test with uint32_t as Index type\n  dispenso::ConcurrentObjectArena<int, uint32_t> arena(16);\n\n  arena.grow_by(100);\n  for (uint32_t i = 0; i < 100; ++i) {\n    arena[i] = static_cast<int>(i * 5);\n  }\n\n  for (uint32_t i = 0; i < 100; ++i) {\n    EXPECT_EQ(arena[i], static_cast<int>(i * 5));\n  }\n\n  EXPECT_EQ(arena.size(), 100u);\n}\n\nTEST(ConcurrentObjectArena, CustomAlignment) {\n  // Test with custom alignment\n  constexpr size_t kAlignment = 128;\n  dispenso::ConcurrentObjectArena<int, size_t, kAlignment> arena(16);\n\n  arena.grow_by(10);\n\n  // Verify buffer pointer alignment\n  const int* buf = arena.getBuffer(0);\n  EXPECT_EQ(reinterpret_cast<uintptr_t>(buf) % kAlignment, 0u);\n}\n\nTEST(ConcurrentObjectArena, GrowByZero) {\n  dispenso::ConcurrentObjectArena<int> arena(16);\n\n  size_t initialSize = arena.size();\n  arena.grow_by(0);\n  EXPECT_EQ(arena.size(), initialSize);\n}\n\nTEST(ConcurrentObjectArena, SingleElementGrowth) {\n  dispenso::ConcurrentObjectArena<int> arena(16);\n\n  // Grow by 1 repeatedly\n  for (int i = 0; i < 50; ++i) {\n    size_t idx = arena.grow_by(1);\n    arena[idx] = i;\n  }\n\n  EXPECT_EQ(arena.size(), 50u);\n\n  for (int i = 0; i < 50; ++i) {\n    EXPECT_EQ(arena[static_cast<size_t>(i)], i);\n  }\n}\n"
  },
  {
    "path": "tests/concurrent_vector_a_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"concurrent_vector_test_common_types.h\"\n\nusing TestTraitsTypes = ::testing::Types<TestTraitsA>;\nDISPENSO_DISABLE_WARNING_PUSH\nDISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\nTYPED_TEST_SUITE(ConcurrentVectorTest, TestTraitsTypes);\nDISPENSO_DISABLE_WARNING_POP\n\n#include \"concurrent_vector_test_common.h\"\n"
  },
  {
    "path": "tests/concurrent_vector_b_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"concurrent_vector_test_common_types.h\"\n\nusing TestTraitsTypes = ::testing::Types<TestTraitsB>;\nDISPENSO_DISABLE_WARNING_PUSH\nDISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\nTYPED_TEST_SUITE(ConcurrentVectorTest, TestTraitsTypes);\nDISPENSO_DISABLE_WARNING_POP\n\n#include \"concurrent_vector_test_common.h\"\n"
  },
  {
    "path": "tests/concurrent_vector_default_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include \"concurrent_vector_test_common_types.h\"\n\nusing TestTraitsTypes = ::testing::Types<dispenso::DefaultConcurrentVectorTraits>;\nDISPENSO_DISABLE_WARNING_PUSH\nDISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\nTYPED_TEST_SUITE(ConcurrentVectorTest, TestTraitsTypes);\nDISPENSO_DISABLE_WARNING_POP\n\n#include \"concurrent_vector_test_common.h\"\n"
  },
  {
    "path": "tests/concurrent_vector_nocache_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Force the opposite cache-pointer mode for this platform so CI exercises\n// whichever code path is normally skipped.\n#if !defined(__aarch64__) && !defined(_M_ARM64)\n#define DISPENSO_HAS_CACHED_PTRS 0\n#else\n#define DISPENSO_HAS_CACHED_PTRS 1\n#endif\n\n#include \"concurrent_vector_test_common_types.h\"\n\nusing TestTraitsTypes = ::testing::Types<dispenso::DefaultConcurrentVectorTraits>;\nDISPENSO_DISABLE_WARNING_PUSH\nDISPENSO_DISABLE_WARNING_ZERO_VARIADIC_MACRO_ARGUMENTS\nTYPED_TEST_SUITE(ConcurrentVectorTest, TestTraitsTypes);\nDISPENSO_DISABLE_WARNING_POP\n\n#include \"concurrent_vector_test_common.h\"\n"
  },
  {
    "path": "tests/concurrent_vector_test_common.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\ntemplate <typename CVec, typename Func>\nvoid runVariedTest(int num, Func func) {\n  {\n    CVec vec;\n    func(num, vec);\n  }\n  {\n    CVec vec(num / 3, dispenso::ReserveTag);\n    func(num, vec);\n  }\n  {\n    CVec vec;\n    vec.reserve(num / 2);\n    func(num, vec);\n  }\n}\n\n#define RUN_VARIED_TEST(len, func, EltType)                      \\\n  runVariedTest<dispenso::ConcurrentVector<EltType, TypeParam>>( \\\n      (len), func<dispenso::ConcurrentVector<EltType, TypeParam>>)\n\ntemplate <typename CVec, typename Func>\nvoid runVariedTest2(int num, int oth, Func func) {\n  {\n    CVec vec;\n    func(num, oth, vec);\n  }\n  {\n    CVec vec(num / 3, dispenso::ReserveTag);\n    func(num, oth, vec);\n  }\n  {\n    CVec vec;\n    vec.reserve(num / 2);\n    func(num, oth, vec);\n  }\n}\n\n#define RUN_VARIED_TEST2(len, oth, func, EltType)                 \\\n  runVariedTest2<dispenso::ConcurrentVector<EltType, TypeParam>>( \\\n      (len), (oth), func<dispenso::ConcurrentVector<EltType, TypeParam>>)\n\ntemplate <typename CVec>\nvoid indexCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  for (size_t index = 0; index < vec.size(); ++index) {\n    EXPECT_EQ(static_cast<int>(index), *vec[index]);\n  }\n\n  const auto& cvec = vec;\n\n  for (size_t index = 0; index < cvec.size(); ++index) {\n    EXPECT_EQ(static_cast<int>(index), *cvec[index]);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, UninitializedIterator) {\n  typename dispenso::ConcurrentVector<int, TypeParam>::iterator iter;\n  (void)iter;\n}\n\nTYPED_TEST(ConcurrentVectorTest, IndexCorrectTiny) {\n  RUN_VARIED_TEST(4, indexCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IndexCorrectSmall) {\n  RUN_VARIED_TEST(12, indexCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IndexCorrectMedium) {\n  RUN_VARIED_TEST(513, indexCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IndexCorrectLarge) {\n  RUN_VARIED_TEST(1 << 13, indexCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IndexCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 13) + 1, indexCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid iterateCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  int index = 0;\n\n  for (auto& v : vec) {\n    EXPECT_EQ(index, *v);\n    ++index;\n  }\n\n  const auto& cvec = vec;\n\n  index = 0;\n  for (auto& v : cvec) {\n    EXPECT_EQ(index, *v);\n    ++index;\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, IterateCorrectTiny) {\n  RUN_VARIED_TEST(3, iterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IterateCorrectSmall) {\n  RUN_VARIED_TEST(37, iterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IterateCorrectMedium) {\n  RUN_VARIED_TEST(768, iterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IterateCorrectLarge) {\n  RUN_VARIED_TEST(1 << 12, iterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, IterateCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 12) + 1, iterateCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid clearAndReuseCorrect(int num, CVec& vec) {\n  for (int round = 0; round < 4; ++round) {\n    vec.clear();\n    for (int i = 0; i < num; ++i) {\n      vec.push_back(std::make_unique<int>(i));\n    }\n\n    int index = 0;\n\n    for (auto& v : vec) {\n      EXPECT_EQ(index, *v);\n      ++index;\n    }\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, ClearAndReuseCorrectTiny) {\n  RUN_VARIED_TEST(1, clearAndReuseCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ClearAndReuseCorrectSmall) {\n  RUN_VARIED_TEST(90, clearAndReuseCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ClearAndReuseCorrectMedium) {\n  RUN_VARIED_TEST(129, clearAndReuseCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ClearAndReuseCorrectLarge) {\n  RUN_VARIED_TEST(1 << 11, clearAndReuseCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ClearAndReuseCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, clearAndReuseCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid copyConstructor(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  for (int round = 0; round < 4; ++round) {\n    CVec newVec(vec);\n    int index = 0;\n    for (auto& v : newVec) {\n      EXPECT_EQ(index, *v);\n      ++index;\n    }\n  }\n  CVec newVec(vec);\n  for (int i = num; i < 2 * num; ++i) {\n    newVec.push_back(std::make_unique<int>(i));\n  }\n\n  int sum = 0;\n  for (auto& v : newVec) {\n    sum += *v;\n  }\n  int maxV = 2 * num - 1;\n\n  EXPECT_EQ(sum, (maxV * (maxV + 1)) / 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, CopyConstructorTiny) {\n  RUN_VARIED_TEST(1, copyConstructor, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyConstructorSmall) {\n  RUN_VARIED_TEST(90, copyConstructor, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyConstructorMedium) {\n  RUN_VARIED_TEST(129, copyConstructor, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyConstructorLarge) {\n  RUN_VARIED_TEST(1 << 11, copyConstructor, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyConstructorLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, copyConstructor, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid moveConstructor(int num, CVec& vec) {\n  for (int round = 0; round < 4; ++round) {\n    EXPECT_TRUE(vec.empty());\n    for (int i = 0; i < num; ++i) {\n      vec.push_back(std::make_unique<int>(i));\n    }\n\n    CVec newVecMoved(std::move(vec));\n    EXPECT_EQ(newVecMoved.size(), num);\n    EXPECT_TRUE(vec.empty());\n    int index = 0;\n    for (auto& v : newVecMoved) {\n      EXPECT_EQ(index, *v);\n      ++index;\n    }\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, MoveConstructorTiny) {\n  RUN_VARIED_TEST(1, moveConstructor, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveConstructorSmall) {\n  RUN_VARIED_TEST(90, moveConstructor, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveConstructorMedium) {\n  RUN_VARIED_TEST(129, moveConstructor, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveConstructorLarge) {\n  RUN_VARIED_TEST(1 << 11, moveConstructor, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveConstructorLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, moveConstructor, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid copyOperator(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_shared<int>(i));\n  }\n  CVec newVec;\n  for (int round = 0; round < 4; ++round) {\n    newVec = vec;\n    EXPECT_EQ(newVec.size(), vec.size());\n    int index = 0;\n    for (auto& v : newVec) {\n      EXPECT_EQ(index, *v);\n      ++index;\n    }\n  }\n\n  for (int i = num; i < 2 * num; ++i) {\n    newVec.push_back(std::make_shared<int>(i));\n  }\n\n  int sum = 0;\n  for (auto& v : newVec) {\n    sum += *v;\n  }\n  int maxV = 2 * num - 1;\n\n  EXPECT_EQ(sum, (maxV * (maxV + 1)) / 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, CopyOperatorTiny) {\n  RUN_VARIED_TEST(7, copyOperator, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyOperatorSmall) {\n  RUN_VARIED_TEST(127, copyOperator, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyOperatorMedium) {\n  RUN_VARIED_TEST(511, copyOperator, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyOperatorLarge) {\n  RUN_VARIED_TEST(1 << 9, copyOperator, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, CopyOperatorLargeP1) {\n  RUN_VARIED_TEST((1 << 9) + 1, copyOperator, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid moveOperator(int num, CVec& vec) {\n  CVec newVecMoved;\n  for (int round = 0; round < 4; ++round) {\n    EXPECT_TRUE(vec.empty());\n    for (int i = 0; i < num; ++i) {\n      vec.push_back(std::make_unique<int>(i));\n    }\n    newVecMoved = std::move(vec);\n    EXPECT_EQ(newVecMoved.size(), num);\n    int index = 0;\n    for (auto& v : newVecMoved) {\n      EXPECT_EQ(index, *v);\n      ++index;\n    }\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, MoveOperatorTiny) {\n  RUN_VARIED_TEST(17, moveOperator, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveOperatorSmall) {\n  RUN_VARIED_TEST(901, moveOperator, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveOperatorMedium) {\n  RUN_VARIED_TEST(1102, moveOperator, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveOperatorLarge) {\n  RUN_VARIED_TEST(1 << 11, moveOperator, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, MoveOperatorLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, moveOperator, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid shrinkToFit(int num, CVec& vec) {\n  vec.shrink_to_fit();\n\n  EXPECT_EQ(vec.capacity(), vec.default_capacity());\n\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  size_t maxCapacity = vec.capacity();\n\n  EXPECT_LE(\n      maxCapacity,\n      2 *\n          std::max<size_t>(\n              static_cast<size_t>(dispenso::detail::nextPow2(vec.size() + 1)),\n              vec.default_capacity()))\n      << \"Num: \" << num << \" default: \" << vec.default_capacity();\n\n  for (int i = 0; i < num / 2; ++i) {\n    vec.pop_back();\n  }\n\n  EXPECT_EQ(vec.capacity(), maxCapacity);\n\n  vec.shrink_to_fit();\n\n  EXPECT_LE(vec.capacity(), maxCapacity);\n\n  size_t afterPopNShrinkCap = vec.capacity();\n\n  EXPECT_LE(\n      afterPopNShrinkCap,\n      2 *\n          std::max<size_t>(\n              static_cast<size_t>(dispenso::detail::nextPow2(vec.size() + 1)),\n              vec.default_capacity()))\n      << \"Size: \" << vec.size() << \" Num: \" << num << \" default: \" << vec.default_capacity();\n\n  vec.clear();\n\n  EXPECT_EQ(vec.capacity(), afterPopNShrinkCap);\n\n  vec.shrink_to_fit();\n\n  EXPECT_EQ(vec.capacity(), vec.default_capacity());\n}\n\nTYPED_TEST(ConcurrentVectorTest, ShrinkToFitTiny) {\n  RUN_VARIED_TEST(17, shrinkToFit, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ShrinkToFitSmall) {\n  RUN_VARIED_TEST(901, shrinkToFit, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ShrinkToFitMedium) {\n  RUN_VARIED_TEST(1102, shrinkToFit, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ShrinkToFitLarge) {\n  RUN_VARIED_TEST(1 << 13, shrinkToFit, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ShrinkToFitLargeP1) {\n  RUN_VARIED_TEST((1 << 13) + 1, shrinkToFit, std::unique_ptr<int>);\n}\n\ntemplate <typename T>\nstruct ReverseWrapper {\n  T& iterable;\n};\n\ntemplate <typename T>\nauto begin(ReverseWrapper<T> w) {\n  return std::rbegin(w.iterable);\n}\n\ntemplate <typename T>\nauto end(ReverseWrapper<T> w) {\n  return std::rend(w.iterable);\n}\n\ntemplate <typename T>\nReverseWrapper<T> reverse(T&& iterable) {\n  return {iterable};\n}\n\ntemplate <typename CVec>\nvoid reverseIterateCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  int index = num;\n\n  for (auto& v : reverse(vec)) {\n    --index;\n    EXPECT_EQ(index, *v);\n  }\n\n  const auto& cvec = vec;\n  index = num;\n  for (auto& v : reverse(cvec)) {\n    --index;\n    EXPECT_EQ(index, *v);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, ReverseIterateCorrectTiny) {\n  RUN_VARIED_TEST(6, reverseIterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ReverseIterateCorrectSmall) {\n  RUN_VARIED_TEST(73, reverseIterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ReverseIterateCorrectMedium) {\n  RUN_VARIED_TEST(677, reverseIterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ReverseIterateCorrectLarge) {\n  RUN_VARIED_TEST(1 << 13, reverseIterateCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ReverseIterateCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 13) + 1, reverseIterateCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid binarySearchCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  for (int i = 0; i < num; ++i) {\n    EXPECT_EQ(\n        std::lower_bound(\n            std::begin(vec), std::end(vec), i, [](const auto& up, int val) { return *up < val; }) -\n            std::begin(vec),\n        i);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, BinarySearchCorrectTiny) {\n  RUN_VARIED_TEST(11, binarySearchCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, BinarySearchCorrectSmall) {\n  RUN_VARIED_TEST(59, binarySearchCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, BinarySearchCorrectMedium) {\n  RUN_VARIED_TEST(711, binarySearchCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, BinarySearchCorrectLarge) {\n  RUN_VARIED_TEST(1 << 11, binarySearchCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, BinarySearchCorrectLargeP3) {\n  RUN_VARIED_TEST((1 << 11) + 3, binarySearchCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid operatorPlusCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  auto start = std::begin(vec);\n  for (int i = 0; i < num; ++i) {\n    EXPECT_EQ(**(start + i), i);\n  }\n  auto end = std::end(vec) - 1;\n  for (int i = 0; i < num; ++i) {\n    EXPECT_EQ(**(end - i), num - i - 1);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, OperatorPlusCorrectTiny) {\n  RUN_VARIED_TEST(11, operatorPlusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorPlusCorrectSmall) {\n  RUN_VARIED_TEST(59, operatorPlusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorPlusCorrectMedium) {\n  RUN_VARIED_TEST(711, operatorPlusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorPlusCorrectLarge) {\n  RUN_VARIED_TEST(1 << 11, operatorPlusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorPlusCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 3, operatorPlusCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid operatorMinusCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  auto start = std::begin(vec);\n  auto it = start;\n  for (int i = 0; i < num; ++i, ++it) {\n    EXPECT_EQ(it - start, i);\n  }\n\n  auto end = std::end(vec);\n\n  EXPECT_EQ(end, it);\n\n  for (int i = 0; i < num; ++i, --it) {\n    EXPECT_EQ(end - it, i);\n  }\n\n  auto mid = start + num / 2;\n  it = start;\n  for (int i = 0; i < num; ++i) {\n    EXPECT_EQ(mid - it++, num / 2 - i);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, OperatorMinusCorrectTiny) {\n  RUN_VARIED_TEST(11, operatorMinusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorMinusCorrectSmall) {\n  RUN_VARIED_TEST(59, operatorMinusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorMinusCorrectMedium) {\n  RUN_VARIED_TEST(711, operatorMinusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorMinusCorrectLarge) {\n  RUN_VARIED_TEST(711, operatorMinusCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorMinusCorrectLargeP1) {\n  RUN_VARIED_TEST(711, operatorMinusCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid operatorComparisonsCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  auto start = std::begin(vec);\n  auto it = start;\n  EXPECT_FALSE(it > start);\n  EXPECT_FALSE(start < it);\n  EXPECT_FALSE(it < start);\n  EXPECT_FALSE(start > it);\n  EXPECT_TRUE(it >= start);\n  EXPECT_TRUE(start <= it);\n  for (int i = 0; i < num; ++i) {\n    ++it;\n    EXPECT_TRUE(it > start);\n    EXPECT_TRUE(it >= start);\n    EXPECT_TRUE(start < it);\n    EXPECT_TRUE(start <= it);\n  }\n\n  auto end = std::end(vec);\n\n  EXPECT_EQ(end, it);\n\n  EXPECT_TRUE(end >= it);\n  EXPECT_TRUE(it <= end);\n  EXPECT_FALSE(end > it);\n  EXPECT_FALSE(it < end);\n  EXPECT_FALSE(it > end);\n  EXPECT_FALSE(end < it);\n  for (int i = 0; i < num; ++i) {\n    --it;\n    EXPECT_TRUE(it < end);\n    EXPECT_TRUE(it <= end);\n    EXPECT_TRUE(end > it);\n    EXPECT_TRUE(end >= it);\n  }\n\n  EXPECT_EQ(start, it);\n\n  int midLen = num / 2;\n  auto mid = start + midLen;\n\n  for (int i = 0; i < midLen; ++i, ++it) {\n    EXPECT_TRUE(mid > it);\n    EXPECT_TRUE(mid >= it);\n    EXPECT_TRUE(it < mid);\n    EXPECT_TRUE(it <= mid);\n  }\n\n  EXPECT_TRUE(mid == it);\n  EXPECT_TRUE(mid >= it);\n  EXPECT_TRUE(it <= mid);\n  EXPECT_FALSE(mid < it);\n  EXPECT_FALSE(it > mid);\n  for (int i = midLen; i < num; ++i) {\n    ++it;\n    EXPECT_TRUE(mid < it);\n    EXPECT_TRUE(mid <= it);\n    EXPECT_TRUE(it > mid);\n    EXPECT_TRUE(it >= mid);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, OperatorComparisonsCorrectTiny) {\n  RUN_VARIED_TEST(0, operatorComparisonsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorComparisonsCorrectSmall) {\n  RUN_VARIED_TEST(65, operatorComparisonsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorComparisonsCorrectMedium) {\n  RUN_VARIED_TEST(511, operatorComparisonsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorComparisonsCorrectLarge) {\n  RUN_VARIED_TEST(1 << 12, operatorComparisonsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorComparisonsCorrectLargeP3) {\n  RUN_VARIED_TEST((1 << 12) + 3, operatorComparisonsCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid operatorBracketsCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  auto start = std::begin(vec);\n  auto it = start;\n  for (int i = 0; i < num; ++i, ++it) {\n    for (int j = -i, k = 0; j < 0; ++j, ++k) {\n      EXPECT_EQ(*it[j], k);\n    }\n    for (int j = 0, k = i; j < num - i; ++j, ++k) {\n      EXPECT_EQ(*it[j], k);\n    }\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, OperatorBracketsCorrectTiny) {\n  RUN_VARIED_TEST(13, operatorBracketsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorBracketsCorrectSmall) {\n  RUN_VARIED_TEST(90, operatorBracketsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorBracketsCorrectMedium) {\n  RUN_VARIED_TEST(399, operatorBracketsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorBracketsCorrectLarge) {\n  RUN_VARIED_TEST(1 << 9, operatorBracketsCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, OperatorBracketsCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 9) + 2, operatorBracketsCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid growByDefaultCorrect(int num, CVec& vec) {\n  for (int i = 0; i < 5; ++i) {\n    vec.grow_by(num);\n  }\n\n  EXPECT_EQ(vec.size(), num * 5);\n\n  for (auto& uv : vec) {\n    EXPECT_TRUE(!uv);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, GrowByDefaultCorrectTiny) {\n  RUN_VARIED_TEST(17, growByDefaultCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByDefaultCorrectSmall) {\n  RUN_VARIED_TEST(91, growByDefaultCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByDefaultCorrectMedium) {\n  RUN_VARIED_TEST(499, growByDefaultCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByDefaultCorrectLarge) {\n  RUN_VARIED_TEST(1 << 10, growByDefaultCorrect, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByDefaultCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 10) + 1, growByDefaultCorrect, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid growByConstantCorrect(int num, CVec& vec) {\n  for (int i = 0; i < 5; ++i) {\n    vec.grow_by(num, std::make_shared<int>(4));\n  }\n\n  size_t result = 0;\n\n  for (auto& v : vec) {\n    result += *v + 1;\n  }\n\n  EXPECT_EQ(result, 5 * vec.size());\n  EXPECT_EQ(result, 5 * 5 * num);\n}\n\nTYPED_TEST(ConcurrentVectorTest, GrowByConstantCorrectTiny) {\n  RUN_VARIED_TEST(12, growByConstantCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConstantCorrectSmall) {\n  RUN_VARIED_TEST(81, growByConstantCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConstantCorrectMedium) {\n  RUN_VARIED_TEST(300, growByConstantCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConstantCorrectLarge) {\n  RUN_VARIED_TEST(1 << 9, growByConstantCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConstantCorrectLargeP7) {\n  RUN_VARIED_TEST((1 << 9) + 7, growByConstantCorrect, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid growByInitListCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.grow_by(\n        {std::make_shared<int>(0),\n         std::make_shared<int>(1),\n         std::make_shared<int>(2),\n         std::make_shared<int>(3),\n         std::make_shared<int>(4),\n         std::make_shared<int>(5),\n         std::make_shared<int>(6),\n         std::make_shared<int>(7),\n         std::make_shared<int>(8),\n         std::make_shared<int>(9),\n         std::make_shared<int>(10)});\n  }\n\n  EXPECT_EQ(vec.size(), 11 * num);\n\n  size_t result = 0;\n\n  for (auto& v : vec) {\n    result += *v;\n  }\n\n  EXPECT_EQ(result, 55 * num);\n}\n\nTYPED_TEST(ConcurrentVectorTest, GrowByInitListCorrectTiny) {\n  RUN_VARIED_TEST(17, growByInitListCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByInitListCorrectSmall) {\n  RUN_VARIED_TEST(91, growByInitListCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByInitListCorrectMedium) {\n  RUN_VARIED_TEST(499, growByInitListCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByInitListCorrectLarge) {\n  RUN_VARIED_TEST(1 << 10, growByInitListCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByInitListCorrectLargeP1) {\n  RUN_VARIED_TEST((1 << 10) + 1, growByInitListCorrect, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid growBySquaredCorrect(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.grow_by(num, std::make_shared<int>(10));\n  }\n\n  size_t result = 0;\n\n  for (auto& v : vec) {\n    result += *v;\n  }\n\n  EXPECT_EQ(result, 10 * vec.size());\n  EXPECT_EQ(result, 10 * num * num);\n}\n\nTYPED_TEST(ConcurrentVectorTest, GrowBySquaredCorrectTiny) {\n  RUN_VARIED_TEST(14, growBySquaredCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowBySquaredCorrectSmall) {\n  RUN_VARIED_TEST(79, growBySquaredCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowBySquaredCorrectMedium) {\n  RUN_VARIED_TEST(129, growBySquaredCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowBySquaredCorrectLarge) {\n  RUN_VARIED_TEST(191, growBySquaredCorrect, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowBySquaredCorrectLargeP1) {\n  RUN_VARIED_TEST(193, growBySquaredCorrect, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid growByConcurrent(int num, int growBy, CVec& vec) {\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, num, dispenso::ParForChunking::kStatic),\n      [&vec, growBy](int i, int end) {\n        while (i + growBy <= end) {\n          vec.grow_by_generator(growBy, [i]() mutable { return std::make_unique<int>(i++); });\n          i += growBy;\n        }\n        vec.grow_by_generator(end - i, [i]() mutable { return std::make_unique<int>(i++); });\n      });\n\n  EXPECT_EQ(vec.size(), num);\n\n  std::vector<uint8_t> which(static_cast<size_t>(num));\n  for (auto& i : vec) {\n    ++which[*i];\n  }\n\n  for (size_t i = 0; i < which.size(); ++i) {\n    EXPECT_EQ(1, which[i]) << \"mismatch for index \" << i;\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, GrowByConcurrentTiny) {\n  RUN_VARIED_TEST2(14, 2, growByConcurrent, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConcurrentSmall) {\n  RUN_VARIED_TEST2(79, 4, growByConcurrent, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConcurrentMedium) {\n  RUN_VARIED_TEST2(200, 8, growByConcurrent, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConcurrentLarge) {\n  RUN_VARIED_TEST2(1 << 8, 16, growByConcurrent, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, GrowByConcurrentLargeP1) {\n  RUN_VARIED_TEST2((1 << 8) + 1, 1, growByConcurrent, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid assignThenPush(int num, CVec& vec) {\n  std::vector<std::shared_ptr<int>> vals;\n  for (int i = 0; i < num; ++i) {\n    vals.push_back(std::make_shared<int>(i));\n  }\n\n  vec.assign(std::begin(vals), std::end(vals));\n\n  for (int i = num; i < 2 * num; ++i) {\n    vec.push_back(std::make_shared<int>(i));\n  }\n\n  int result = 0;\n\n  for (auto& v : vec) {\n    result += *v;\n  }\n\n  int maxV = 2 * num - 1;\n\n  EXPECT_EQ(result, (maxV * (maxV + 1)) / 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, AssignThenPushTiny) {\n  RUN_VARIED_TEST(11, assignThenPush, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AssignThenPushSmall) {\n  RUN_VARIED_TEST(81, assignThenPush, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AssignThenPushMedium) {\n  RUN_VARIED_TEST(317, assignThenPush, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AssignThenPushLarge) {\n  RUN_VARIED_TEST(1 << 9, assignThenPush, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AssignThenPushLargeP1) {\n  RUN_VARIED_TEST((1 << 9) + 1, assignThenPush, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid at(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  int result = 0;\n  for (int i = 0; i < num; ++i) {\n    result += *vec.at(i);\n  }\n\n  int maxV = num - 1;\n\n  EXPECT_EQ(result, (maxV * (maxV + 1)) / 2);\n\n#if defined(__cpp_exceptions)\n  bool caught = false;\n  try {\n    EXPECT_EQ(0, *vec.at(num));\n  } catch (const std::out_of_range&) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n#endif // exceptions\n}\n\nTYPED_TEST(ConcurrentVectorTest, AtTiny) {\n  RUN_VARIED_TEST(8, at, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AtSmall) {\n  RUN_VARIED_TEST(65, at, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AtMedium) {\n  RUN_VARIED_TEST(255, at, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AtLarge) {\n  RUN_VARIED_TEST(1 << 9, at, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, AtLargeP2) {\n  RUN_VARIED_TEST((1 << 9) + 2, at, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid resize(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  vec.resize(num / 2);\n\n  int result = 0;\n  for (auto& v : vec) {\n    if (v) {\n      result += *v;\n    }\n  }\n\n  int maxV = num / 2 - 1;\n\n  EXPECT_EQ(result, (maxV * (maxV + 1)) / 2);\n\n  // default init for new values should be null\n  vec.resize(num);\n\n  result = 0;\n  for (auto& v : vec) {\n    if (v) {\n      result += *v;\n    }\n  }\n\n  EXPECT_EQ(result, (maxV * (maxV + 1)) / 2);\n\n  vec.resize(num * 2, std::make_shared<int>(5));\n\n  result = 0;\n  for (auto& v : vec) {\n    if (v) {\n      result += *v;\n    }\n  }\n\n  EXPECT_EQ(result, 5 * num + (maxV * (maxV + 1)) / 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, ResizeTiny) {\n  RUN_VARIED_TEST(9, resize, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ResizeSmall) {\n  RUN_VARIED_TEST(63, resize, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ResizeMedium) {\n  RUN_VARIED_TEST(256, resize, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ResizeLarge) {\n  RUN_VARIED_TEST(1 << 10, resize, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, ResizeLargeP1) {\n  RUN_VARIED_TEST((1 << 10) + 1, resize, std::shared_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid comparison(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(i);\n  }\n\n  EXPECT_EQ(vec, vec);\n\n  auto vec2 = vec;\n\n  EXPECT_GE(vec, vec2);\n  EXPECT_LE(vec, vec2);\n\n  EXPECT_FALSE(vec < vec2);\n  EXPECT_FALSE(vec2 < vec);\n\n  vec2[num - 1] = 2 * num;\n\n  EXPECT_LE(vec, vec2);\n  EXPECT_LT(vec, vec2);\n\n  EXPECT_GE(vec2, vec);\n  EXPECT_GT(vec2, vec);\n\n  EXPECT_FALSE(vec > vec2);\n  EXPECT_FALSE(vec >= vec2);\n  EXPECT_FALSE(vec2 < vec);\n  EXPECT_FALSE(vec2 <= vec);\n\n  EXPECT_NE(vec, vec2);\n  EXPECT_FALSE(vec == vec2);\n\n  vec2.pop_back();\n\n  EXPECT_LE(vec2, vec);\n  EXPECT_LT(vec2, vec);\n\n  EXPECT_GE(vec, vec2);\n  EXPECT_GT(vec, vec2);\n\n  EXPECT_FALSE(vec2 > vec);\n  EXPECT_FALSE(vec2 >= vec);\n  EXPECT_FALSE(vec < vec2);\n  EXPECT_FALSE(vec <= vec2);\n\n  EXPECT_NE(vec, vec2);\n  EXPECT_FALSE(vec == vec2);\n\n  vec2.push_back(num - 1);\n\n  EXPECT_EQ(vec, vec2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, ComparisonTiny) {\n  RUN_VARIED_TEST(12, comparison, int);\n}\nTYPED_TEST(ConcurrentVectorTest, ComparisonSmall) {\n  RUN_VARIED_TEST(77, comparison, int);\n}\nTYPED_TEST(ConcurrentVectorTest, ComparisonMedium) {\n  RUN_VARIED_TEST(222, comparison, int);\n}\nTYPED_TEST(ConcurrentVectorTest, ComparisonLarge) {\n  RUN_VARIED_TEST(1 << 10, comparison, int);\n}\nTYPED_TEST(ConcurrentVectorTest, ComparisonLargeP1) {\n  RUN_VARIED_TEST((1 << 10) + 1, comparison, int);\n}\n\ntemplate <typename V>\nstd::string printVec(const V& vec) {\n  if (vec.size() > 20) {\n    return \"too long to print\";\n  }\n  std::string ret;\n  for (auto& v : vec) {\n    ret += std::to_string(*v) + \" \";\n  }\n  return ret;\n}\n\ninline std::string printVec(const dispenso::ConcurrentVector<int>& vec) {\n  if (vec.size() > 20) {\n    return \"too long to print\";\n  }\n  std::string ret;\n  for (auto v : vec) {\n    ret += std::to_string(v) + \" \";\n  }\n  return ret;\n}\n\ninline std::string printVec(const std::vector<int>& vec) {\n  if (vec.size() > 20) {\n    return \"too long to print\";\n  }\n  std::string ret;\n  for (auto v : vec) {\n    ret += std::to_string(v) + \" \";\n  }\n  return ret;\n}\n\n#define EXPECT_VEC_SUM(vec, num)                                                        \\\n  do {                                                                                  \\\n    int64_t maxV = (num) - 1;                                                           \\\n    int64_t result = 0;                                                                 \\\n    for (auto& v : vec) {                                                               \\\n      result += *v;                                                                     \\\n    }                                                                                   \\\n    EXPECT_EQ(result, (maxV * (maxV + 1)) / 2)                                          \\\n        << \"vec size is \" << vec.size() << \" num is \" << (num) << \" \" << printVec(vec); \\\n  } while (false)\n\n#define EXPECT_VEC_SUM_MINUS(vec, num, minus)                   \\\n  do {                                                          \\\n    int64_t maxV = (num) - 1;                                   \\\n    int64_t result = 0;                                         \\\n    for (auto& v : vec) {                                       \\\n      result += *v;                                             \\\n    }                                                           \\\n    EXPECT_EQ(result, (maxV * (maxV + 1)) / 2 - (minus))        \\\n        << \"vec size is \" << vec.size() << \" num is \" << (num); \\\n  } while (false)\n\ntemplate <typename CVec>\nvoid swap(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  CVec vec2;\n  for (int i = 0; i < num / 2; ++i) {\n    vec2.push_back(std::make_unique<int>(i));\n  }\n\n  EXPECT_VEC_SUM(vec, num);\n  EXPECT_VEC_SUM(vec2, num / 2);\n\n  swap(vec, vec2);\n\n  EXPECT_VEC_SUM(vec, num / 2);\n  EXPECT_VEC_SUM(vec2, num);\n\n  vec.swap(vec2);\n\n  EXPECT_VEC_SUM(vec, num);\n  EXPECT_VEC_SUM(vec2, num / 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, SwapTiny) {\n  RUN_VARIED_TEST(12, swap, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, SwapSmall) {\n  RUN_VARIED_TEST(77, swap, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, SwapMedium) {\n  RUN_VARIED_TEST(222, swap, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, SwapLarge) {\n  RUN_VARIED_TEST(1 << 11, swap, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, SwapLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, swap, std::unique_ptr<int>);\n}\n\nTYPED_TEST(ConcurrentVectorTest, IterToConstIter) {\n  dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam> vec;\n  typename dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>::iterator it = vec.begin();\n  typename dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>::const_iterator cit = it;\n  EXPECT_EQ(cit, it);\n}\n\ntemplate <typename CVec>\nvoid eraseOne(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n  // 0 1 2 3 4 5 6 7 8 9 10 11\n  EXPECT_VEC_SUM(vec, num);\n\n  ASSERT_EQ(vec.end(), vec.erase(vec.end()));\n\n  // 0 1 2 3 4 5 6 7 8 9 10 11\n  ASSERT_EQ(vec.size(), num);\n\n  vec.erase(vec.end() - 1);\n\n  // 0 1 2 3 4 5 6 7 8 9 10\n  ASSERT_EQ(vec.size(), num - 1);\n\n  EXPECT_VEC_SUM(vec, num - 1);\n\n  vec.erase(vec.end() - 1);\n\n  // 0 1 2 3 4 5 6 7 8 9\n  EXPECT_VEC_SUM(vec, num - 2);\n\n  vec.erase(vec.begin());\n\n  // 1 2 3 4 5 6 7 8 9\n  ASSERT_EQ(vec.size(), num - 3) << printVec(vec);\n\n  EXPECT_VEC_SUM(vec, num - 2);\n\n  vec.erase(vec.begin() + 1);\n\n  // 1 3 4 5 6 7 8 9\n  EXPECT_VEC_SUM_MINUS(vec, num - 2, 2);\n}\n\nTYPED_TEST(ConcurrentVectorTest, EraseOneTiny) {\n  RUN_VARIED_TEST(12, eraseOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseOneSmall) {\n  RUN_VARIED_TEST(77, eraseOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseOneMedium) {\n  RUN_VARIED_TEST(222, eraseOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseOneLarge) {\n  RUN_VARIED_TEST(1 << 11, eraseOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseOneLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, eraseOne, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid eraseRange(int num, CVec& vec) {\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n  }\n\n  // 0 1 2 3 4 5 6 7 8 9 10 11\n  EXPECT_VEC_SUM(vec, num);\n\n  vec.erase(vec.end() - 1);\n\n  // 0 1 2 3 4 5 6 7 8 9 10\n  EXPECT_VEC_SUM(vec, num - 1);\n\n  vec.erase(vec.end() - 5, vec.end());\n\n  // 0 1 2 3 4 5\n  EXPECT_VEC_SUM(vec, num - 6);\n\n  vec.erase(vec.begin() + 1, vec.begin() + 3);\n\n  // 0 3 4 5\n  EXPECT_EQ(vec.size(), num - 8);\n\n  EXPECT_VEC_SUM_MINUS(vec, num - 6, 3);\n\n  //\n  vec.erase(vec.begin(), vec.end());\n\n  EXPECT_EQ(vec.size(), 0);\n}\n\nTYPED_TEST(ConcurrentVectorTest, EraseRangeTiny) {\n  RUN_VARIED_TEST(12, eraseRange, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseRangeSmall) {\n  RUN_VARIED_TEST(66, eraseRange, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseRangeMedium) {\n  RUN_VARIED_TEST(111, eraseRange, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseRangeLarge) {\n  RUN_VARIED_TEST(1 << 9, eraseRange, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, EraseRangeLargeP1) {\n  RUN_VARIED_TEST((1 << 9) + 1, eraseRange, std::unique_ptr<int>);\n}\n\n#define EXPECT_CONTAINER_EQ(a, b)                                                \\\n  do {                                                                           \\\n    ASSERT_EQ(a.size(), b.size());                                               \\\n    for (size_t i = 0; i < a.size(); ++i) {                                      \\\n      EXPECT_EQ(a[i], *b[i]) << \"index: \" << i << \"\\n\"                           \\\n                             << printVec(a) << \"\\n===========================\\n\" \\\n                             << printVec(b);                                     \\\n    }                                                                            \\\n  } while (0)\n\ntemplate <typename CVec>\nvoid insertOne(int num, CVec& vec) {\n  // Utilize std::vector as our baseline\n\n  std::vector<int> baseline;\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_unique<int>(i));\n    baseline.push_back(i);\n  }\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(vec.begin(), std::make_unique<int>(5));\n  baseline.insert(baseline.begin(), 5);\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(vec.begin() + 7, std::make_unique<int>(77));\n  baseline.insert(baseline.begin() + 7, 77);\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(vec.end() - 1, std::make_unique<int>(33));\n  baseline.insert(baseline.end() - 1, 33);\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(vec.end(), std::make_unique<int>(999));\n  baseline.insert(baseline.end(), 999);\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n}\n\nTYPED_TEST(ConcurrentVectorTest, InsertOneTiny) {\n  RUN_VARIED_TEST(11, insertOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertOneSmall) {\n  RUN_VARIED_TEST(40, insertOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertOneMedium) {\n  RUN_VARIED_TEST(200, insertOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertOneLarge) {\n  RUN_VARIED_TEST(1 << 10, insertOne, std::unique_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertOneLargeP1) {\n  RUN_VARIED_TEST((1 << 10) + 1, insertOne, std::unique_ptr<int>);\n}\n\ntemplate <typename CVec>\nvoid insertRange(int num, CVec& vec) {\n  // Utilize std::vector as our baseline\n\n  std::vector<int> baseline;\n  for (int i = 0; i < num; ++i) {\n    vec.push_back(std::make_shared<int>(i));\n    baseline.push_back(i);\n  }\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(vec.begin(), 4, std::make_shared<int>(5));\n  baseline.insert(baseline.begin(), 4, 5);\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(\n      vec.begin() + 7,\n      {std::make_shared<int>(1),\n       std::make_shared<int>(2),\n       std::make_shared<int>(3),\n       std::make_shared<int>(4)});\n  baseline.insert(baseline.begin() + 7, {1, 2, 3, 4});\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(\n      vec.end() - 1,\n      {std::make_shared<int>(1),\n       std::make_shared<int>(2),\n       std::make_shared<int>(3),\n       std::make_shared<int>(4)});\n  baseline.insert(baseline.end() - 1, {1, 2, 3, 4});\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n\n  vec.insert(\n      vec.end(),\n      {std::make_shared<int>(1),\n       std::make_shared<int>(2),\n       std::make_shared<int>(3),\n       std::make_shared<int>(4)});\n  baseline.insert(baseline.end(), {1, 2, 3, 4});\n\n  EXPECT_CONTAINER_EQ(baseline, vec);\n}\n\nTYPED_TEST(ConcurrentVectorTest, InsertRangeTiny) {\n  RUN_VARIED_TEST(13, insertRange, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertRangeSmall) {\n  RUN_VARIED_TEST(111, insertRange, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertRangeMedium) {\n  RUN_VARIED_TEST(600, insertRange, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertRangeLarge) {\n  RUN_VARIED_TEST(1 << 11, insertRange, std::shared_ptr<int>);\n}\nTYPED_TEST(ConcurrentVectorTest, InsertRangeLargeP1) {\n  RUN_VARIED_TEST((1 << 11) + 1, insertRange, std::shared_ptr<int>);\n}\n\ntemplate <typename ContainerInit, typename ContainerPush>\nvoid parallelImplGrowBy(\n    int length,\n    int growBy,\n    ContainerInit containerInit,\n    ContainerPush containerPush) {\n  auto values = containerInit();\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(0, length, dispenso::ParForChunking::kStatic),\n      [&values, containerPush, growBy](int i, int end) {\n        while (i + growBy <= end) {\n          containerPush(values, i, i + growBy);\n          i += growBy;\n        }\n        containerPush(values, i, end);\n      });\n\n  EXPECT_VEC_SUM(values, length);\n}\n\nTYPED_TEST(ConcurrentVectorTest, InsertRangeLargeGrowBy10) {\n  parallelImplGrowBy(\n      (1 << 18),\n      10,\n      []() { return dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>(); },\n      [](dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>& c, int i, int end) {\n        c.grow_by_generator(end - i, [i]() mutable { return std::make_unique<int>(i++); });\n      });\n}\n\nTYPED_TEST(ConcurrentVectorTest, InsertRangeLargeGrowBy100) {\n  parallelImplGrowBy(\n      (1 << 18),\n      100,\n      []() { return dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>(); },\n      [](dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam>& c, int i, int end) {\n        c.grow_by_generator(end - i, [i]() mutable { return std::make_unique<int>(i++); });\n      });\n}\n\nstruct NonMovable {\n  int i;\n  NonMovable(int val) : i(val) {}\n  NonMovable(NonMovable&& other) = delete;\n  NonMovable& operator=(NonMovable&& other) = delete;\n};\n\nTYPED_TEST(ConcurrentVectorTest, NonMovableObjects) {\n  dispenso::ConcurrentVector<NonMovable, TypeParam> vec;\n  for (int i = 0; i < 10; ++i) {\n    vec.emplace_back(i);\n  }\n  int idx = 0;\n  for (auto& nmv : vec) {\n    EXPECT_EQ(nmv.i, idx++);\n  }\n\n  dispenso::ConcurrentVector<NonMovable, TypeParam> other(std::move(vec));\n\n  idx = 0;\n  for (auto& nmv : other) {\n    EXPECT_EQ(nmv.i, idx++);\n  }\n}\n\nTYPED_TEST(ConcurrentVectorTest, OtherConstructorsTest) {\n  dispenso::ConcurrentVector<std::unique_ptr<int>, TypeParam> a(193);\n  size_t remaining = 193;\n  for (auto& ap : a) {\n    EXPECT_FALSE(ap);\n    --remaining;\n  }\n  EXPECT_EQ(remaining, 0);\n\n  dispenso::ConcurrentVector<std::shared_ptr<int>, TypeParam> b(211, std::make_shared<int>(5));\n  remaining = 211;\n  for (auto& bp : b) {\n    ASSERT_TRUE(bp);\n    EXPECT_EQ(*bp, 5);\n    --remaining;\n  }\n  EXPECT_EQ(remaining, 0);\n\n  dispenso::ConcurrentVector<int, TypeParam> c({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});\n\n  int v = 0;\n  for (auto cv : c) {\n    EXPECT_EQ(cv, v++);\n  }\n}\n"
  },
  {
    "path": "tests/concurrent_vector_test_common_types.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/concurrent_vector.h>\n\n#include <algorithm>\n#include <memory>\n#include <vector>\n\n#include <dispenso/parallel_for.h>\n#include <gtest/gtest.h>\n\ntemplate <typename Traits>\nclass ConcurrentVectorTest : public testing::Test {\n public:\n};\n\nusing dispenso::ConcurrentVectorReallocStrategy;\n\nstruct TestTraitsA {\n  static constexpr bool kPreferBuffersInline = false;\n  static constexpr ConcurrentVectorReallocStrategy kReallocStrategy =\n      ConcurrentVectorReallocStrategy::kHalfBufferAhead;\n  static constexpr bool kIteratorPreferSpeed = false;\n};\n\nstruct TestTraitsB {\n  static constexpr bool kPreferBuffersInline = true;\n  static constexpr ConcurrentVectorReallocStrategy kReallocStrategy =\n      ConcurrentVectorReallocStrategy::kFullBufferAhead;\n  static constexpr bool kIteratorPreferSpeed = true;\n};\n"
  },
  {
    "path": "tests/fast_math/CMakeLists.txt",
    "content": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\ncmake_minimum_required(VERSION 3.14)\n\n# Apply SIMD ISA flags and Highway linkage from parent.\nset(FAST_MATH_EXTRA_FLAGS ${DISPENSO_FAST_MATH_SIMD_FLAGS})\nset(FAST_MATH_EXTRA_LIBS \"\")\nif(DISPENSO_FAST_MATH_HIGHWAY AND TARGET hwy)\n  list(APPEND FAST_MATH_EXTRA_LIBS hwy)\n  # Treat Highway as a system include to suppress warnings from its headers.\n  if(MSVC)\n    list(APPEND FAST_MATH_EXTRA_FLAGS /external:I ${hwy_SOURCE_DIR})\n  else()\n    list(APPEND FAST_MATH_EXTRA_FLAGS -isystem${hwy_SOURCE_DIR})\n  endif()\nendif()\n\n# Scalar function tests (link eval.cpp helper)\nfile(GLOB FAST_MATH_TEST_FILES CONFIGURE_DEPENDS \"*_test.cpp\")\n\n# Separate SIMD backend tests (no eval.cpp dependency)\nset(SIMD_TEST_FILES\n  ${CMAKE_CURRENT_SOURCE_DIR}/sse_test.cpp\n  ${CMAKE_CURRENT_SOURCE_DIR}/avx_test.cpp\n  ${CMAKE_CURRENT_SOURCE_DIR}/avx512_test.cpp\n  ${CMAKE_CURRENT_SOURCE_DIR}/neon_test.cpp\n  ${CMAKE_CURRENT_SOURCE_DIR}/hwy_test.cpp\n)\n\nforeach(SIMD_FILE ${SIMD_TEST_FILES})\n  list(REMOVE_ITEM FAST_MATH_TEST_FILES ${SIMD_FILE})\nendforeach()\n\n# Scalar / util tests: each links eval.cpp\nforeach(TEST_FILE ${FAST_MATH_TEST_FILES})\n  set(TEST_NAME)\n  get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n  set(TEST_NAME \"fast_math_${TEST_NAME}\")\n  add_executable(${TEST_NAME} ${TEST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/eval.cpp)\n  target_compile_features(${TEST_NAME} PRIVATE cxx_std_17)\n  target_compile_options(${TEST_NAME} PRIVATE\n    $<$<CXX_COMPILER_ID:MSVC>:/W3 /WX>\n    $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion -Werror>\n    ${FAST_MATH_EXTRA_FLAGS}\n  )\n  target_link_libraries(${TEST_NAME} gmock_main gtest dispenso ${FAST_MATH_EXTRA_LIBS})\n  gtest_discover_tests(${TEST_NAME}\n    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}\n    PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}\"\n    LABELS \"fast_math\")\n  set_target_properties(${TEST_NAME} PROPERTIES FOLDER tests/fast_math)\nendforeach()\n\n# Standalone evaluation tools (not gtests — no eval.cpp, no gtest linkage).\nforeach(EVAL_FILE\n    ${CMAKE_CURRENT_SOURCE_DIR}/ulp_eval.cpp\n    ${CMAKE_CURRENT_SOURCE_DIR}/pow_ulp_eval.cpp)\n  if(NOT EXISTS ${EVAL_FILE})\n    continue()\n  endif()\n  get_filename_component(EVAL_NAME ${EVAL_FILE} NAME_WE)\n  set(EVAL_NAME \"fast_math_${EVAL_NAME}\")\n  add_executable(${EVAL_NAME} ${EVAL_FILE})\n  target_compile_features(${EVAL_NAME} PRIVATE cxx_std_17)\n  target_compile_options(${EVAL_NAME} PRIVATE\n    $<$<CXX_COMPILER_ID:MSVC>:/W3>\n    $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion>\n    ${FAST_MATH_EXTRA_FLAGS}\n  )\n  target_link_libraries(${EVAL_NAME} dispenso ${FAST_MATH_EXTRA_LIBS})\n  set_target_properties(${EVAL_NAME} PROPERTIES FOLDER tests/fast_math)\nendforeach()\n\n# SIMD backend tests: no eval.cpp dependency.\nforeach(TEST_FILE ${SIMD_TEST_FILES})\n  set(TEST_NAME)\n  get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)\n  set(TEST_NAME \"fast_math_${TEST_NAME}\")\n  add_executable(${TEST_NAME} ${TEST_FILE})\n  target_compile_features(${TEST_NAME} PRIVATE cxx_std_17)\n  target_compile_options(${TEST_NAME} PRIVATE\n    $<$<CXX_COMPILER_ID:MSVC>:/W3 /WX>\n    $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Wconversion -Wno-sign-conversion -Werror>\n    ${FAST_MATH_EXTRA_FLAGS}\n  )\n  target_link_libraries(${TEST_NAME} gmock_main gtest dispenso ${FAST_MATH_EXTRA_LIBS})\n  gtest_discover_tests(${TEST_NAME}\n    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}\n    PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}\"\n    LABELS \"fast_math\")\n  set_target_properties(${TEST_NAME} PROPERTIES FOLDER tests/fast_math)\nendforeach()\n"
  },
  {
    "path": "tests/fast_math/acos_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Acos, OutOfRange) {\n  auto res = dfm::acos(1.00001f);\n  EXPECT_NE(res, res);\n  res = dfm::acos(-1.00001f);\n  EXPECT_NE(res, res);\n}\n\nTEST(Acos, SpecialVals) {\n  auto res = dfm::acos(-1.0f);\n  EXPECT_EQ(res, kPi);\n  res = dfm::acos(1.0f);\n  EXPECT_EQ(res, 0.0f);\n  res = dfm::acos(0.0f);\n  EXPECT_FLOAT_EQ(res, kPi_2);\n}\n\n// Apple's acos implmentation for x86_64 does not match their implementation for\n// ARM, nor does it match glibc or Window's acos implementations in the last bit(s).\n#if defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))\nconstexpr uint32_t kMaxUlpsError = 4;\n#else\nconstexpr uint32_t kMaxUlpsError = 3;\n#endif // apple x86(_64)\n\nTEST(Acos, Range) {\n  uint32_t ulps = dfm::evalAccuracy(acosf, dfm::acos<float>, -1.0f, 1.0f);\n  EXPECT_LE(ulps, kMaxUlpsError);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(AcosAll, ::acosf, dfm::acos, -1.0f, 1.0f, kMaxUlpsError)\n\n// Special values tested across all SIMD backends (including out-of-range → NaN).\nstatic const float kAcosSpecials[] = {\n    0.0f,\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    0.25f,\n    -0.25f,\n    0.75f,\n    0.99999f,\n    1.00001f,\n    -1.00001f,\n    2.0f,\n    -5.0f,\n    10.0f,\n    -10.0f,\n    100.0f,\n    -100.0f};\nFAST_MATH_SPECIAL_TESTS(AcosSpecial, ::acosf, dfm::acos, kAcosSpecials, kMaxUlpsError)\n"
  },
  {
    "path": "tests/fast_math/asin_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nusing namespace dispenso::fast_math::testing;\n\nTEST(Asin, OutOfRange) {\n  auto res = dispenso::fast_math::asin(1.00001f);\n  EXPECT_NE(res, res);\n  res = dispenso::fast_math::asin(-1.00001f);\n  EXPECT_NE(res, res);\n}\n\nTEST(Asin, SpecialVals) {\n  auto res = dispenso::fast_math::asin(-1.0f);\n  EXPECT_EQ(res, -kPi_2);\n  res = dispenso::fast_math::asin(1.0f);\n  EXPECT_EQ(res, kPi_2);\n  res = dispenso::fast_math::asin(0.0f);\n  EXPECT_EQ(res, 0.0f);\n}\n\nTEST(Asin, Range) {\n  uint32_t ulps =\n      dispenso::fast_math::evalAccuracy(asinf, dispenso::fast_math::asin<float>, -1.0f, 1.0f);\n  EXPECT_LE(ulps, 3);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nnamespace dfm = dispenso::fast_math;\nconstexpr uint32_t kAsinMaxUlps = 3;\nFAST_MATH_ACCURACY_TESTS(AsinAll, ::asinf, dfm::asin, -1.0f, 1.0f, kAsinMaxUlps)\n\n// Special values tested across all SIMD backends (including out-of-range → NaN).\nstatic const float kAsinSpecials[] = {\n    0.0f,\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    0.25f,\n    -0.25f,\n    0.9f,\n    0.99999f,\n    1.00001f,\n    -1.00001f,\n    2.0f,\n    -5.0f,\n    10.0f,\n    -10.0f,\n    100.0f,\n    -100.0f};\nFAST_MATH_SPECIAL_TESTS(AsinSpecial, ::asinf, dfm::asin, kAsinSpecials, kAsinMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/atan2_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <random>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Atan2, SpecialVals) {\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  auto res = dispenso::fast_math::atan2(0.0f, -1.0f);\n  EXPECT_EQ(res, kPi);\n  res = dispenso::fast_math::atan2(-0.0f, -1.0f);\n  EXPECT_EQ(res, -kPi);\n\n  res = dispenso::fast_math::atan2(0.0f, 1.0f);\n  EXPECT_EQ(res, static_cast<float>(0.0f));\n  res = dispenso::fast_math::atan2(-0.0f, 1.0f);\n  EXPECT_EQ(\n      dispenso::fast_math::bit_cast<uint32_t>(res), dispenso::fast_math::bit_cast<uint32_t>(-0.0f));\n\n  res = dispenso::fast_math::atan2(-1.0f, 0.0f);\n  EXPECT_EQ(res, -kPi_2);\n  res = dispenso::fast_math::atan2(1.0f, 0.0f);\n  EXPECT_EQ(res, kPi_2);\n  res = dispenso::fast_math::atan2(0.0f, -0.0f);\n  EXPECT_EQ(res, kPi);\n  res = dispenso::fast_math::atan2(-0.0f, -0.0f);\n  EXPECT_EQ(res, -kPi);\n  res = dispenso::fast_math::atan2(0.0f, 0.0f);\n  EXPECT_EQ(res, 0.0f);\n  res = dispenso::fast_math::atan2(-0.0f, 0.0f);\n  EXPECT_EQ(res, 0.0f);\n\n  res = dispenso::fast_math::atan2(kNaN, 1.0f);\n  EXPECT_NE(res, res);\n  res = dispenso::fast_math::atan2(1.0f, kNaN);\n  EXPECT_NE(res, res);\n  res = dispenso::fast_math::atan2(kNaN, kNaN);\n  EXPECT_NE(res, res);\n\n  res = dispenso::fast_math::atan2(1.0f, -kInf);\n  EXPECT_EQ(res, kPi);\n  res = dispenso::fast_math::atan2(-1.0f, -kInf);\n  EXPECT_EQ(res, -kPi);\n\n  res = dispenso::fast_math::atan2(1.0f, kInf);\n  EXPECT_EQ(res, static_cast<float>(0.0f));\n  res = dispenso::fast_math::atan2(-1.0f, kInf);\n  EXPECT_EQ(res, static_cast<float>(0.0f));\n\n  res = dispenso::fast_math::atan2(kInf, 1.0f);\n  EXPECT_EQ(res, kPi_2);\n}\n\nstruct BoundsTraits {\n  static constexpr bool kBoundsValues = true;\n  static constexpr bool kMaxAccuracy = false; // This isn't actually used\n};\n\nTEST(Atan2WBounds, SpecialVals) {\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n\n  auto atan2_bounds = dispenso::fast_math::atan2<float, BoundsTraits>;\n\n  auto res = atan2_bounds(kInf, -1.0f);\n  EXPECT_EQ(res, -kPi_2);\n\n  res = atan2_bounds(kInf, -kInf);\n  EXPECT_FLOAT_EQ(res, 3.0f * kPi_4);\n  res = atan2_bounds(-kInf, -kInf);\n  EXPECT_FLOAT_EQ(res, -3.0f * kPi_4);\n\n  res = atan2_bounds(kInf, kInf);\n  EXPECT_FLOAT_EQ(res, kPi_4);\n  res = atan2_bounds(-kInf, kInf);\n  EXPECT_FLOAT_EQ(res, -kPi_4);\n}\n\nTEST(Atan2, RangeNearZero) {\n  constexpr int32_t kMax = 2048;\n\n  float quantizer = 0.5f;\n  quantizer *= quantizer;\n  quantizer *= quantizer;\n  quantizer *= quantizer;\n  quantizer *= 0.25f;\n\n  uint32_t maxUlps = 0;\n  for (int32_t y = -kMax; y <= kMax; ++y) {\n    for (int32_t x = -kMax; x <= kMax; ++x) {\n      float yf = static_cast<float>(y) * quantizer;\n      float xf = static_cast<float>(x) * quantizer;\n      maxUlps = std::max(\n          maxUlps,\n          dispenso::fast_math::float_distance(\n              ::atan2f(yf, xf), dispenso::fast_math::atan2(yf, xf)));\n    }\n  }\n  EXPECT_LE(maxUlps, 3);\n}\n\nTEST(Atan, RandomSamples) {\n  constexpr size_t kNumSamples = 1 << 24;\n\n  std::mt19937 gen(77); // Standard mersenne_twister_engine seeded with rd()\n  std::uniform_real_distribution<float> dis(-1e5f, 1e5f);\n\n  uint32_t maxUlps = 0;\n  for (size_t i = 0; i < kNumSamples; ++i) {\n    // get random sample\n    float yf = dis(gen);\n    float xf = dis(gen);\n    float gt = ::atan2f(yf, xf);\n    float apx = dispenso::fast_math::atan2(yf, xf);\n    uint32_t ulps = dispenso::fast_math::float_distance(gt, apx);\n    maxUlps = std::max(maxUlps, ulps);\n  }\n\n  EXPECT_LE(maxUlps, 3);\n}\n\n// Wrappers for traits variants — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt atan2_max(Flt y, Flt x) {\n  return dfm::atan2<Flt, dfm::MaxAccuracyTraits>(y, x);\n}\n\n// Default atan2 handles all edge cases (NaN, Inf, zero-sign).\nconstexpr uint32_t kAtan2Ulps = 3;\n// clang-format off\nstatic const float kAtan2SpecialY[] = {\n    1.0f, -1.0f, 0.0f, 1.0f,                                           // basic quadrants\n    0.0f, -0.0f, 1.0f, -1.0f,                                          // axis values\n    0.0f, -0.0f, 0.0f, -0.0f,                                          // zero-zero combos\n    1e6f, 1.0f, 0.001f,                                                 // varied magnitudes\n    std::numeric_limits<float>::quiet_NaN(), 1.0f,                      // NaN\n    std::numeric_limits<float>::quiet_NaN(),\n    1.0f, -1.0f, std::numeric_limits<float>::infinity(),                // inf cases\n    -std::numeric_limits<float>::infinity()};\nstatic const float kAtan2SpecialX[] = {\n    1.0f, 1.0f, 1.0f, -1.0f,\n    -1.0f, -1.0f, 0.0f, 0.0f,\n    0.0f, 0.0f, -0.0f, -0.0f,\n    1.0f, 1e6f, 0.001f,\n    1.0f, std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity(),\n    1.0f, 1.0f};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    Atan2DefaultSpecial,\n    ::atan2f,\n    dfm::atan2,\n    kAtan2SpecialY,\n    kAtan2SpecialX,\n    kAtan2Ulps)\n\n// MaxAccuracy additionally handles both-inf quadrant cases.\n// clang-format off\nstatic const float kAtan2MaxAccY[] = {\n    1.0f, -1.0f, 0.0f, 1.0f,                                           // basic quadrants\n    0.0f, -0.0f, 1.0f, -1.0f,                                          // axis values\n    0.0f, -0.0f, 0.0f, -0.0f,                                          // zero-zero combos\n    std::numeric_limits<float>::quiet_NaN(), 1.0f,                      // NaN\n    std::numeric_limits<float>::quiet_NaN(),\n    1.0f, -1.0f,                                                        // one-inf\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::infinity(),                              // inf-inf quadrants\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nstatic const float kAtan2MaxAccX[] = {\n    1.0f, 1.0f, 1.0f, -1.0f,\n    -1.0f, -1.0f, 0.0f, 0.0f,\n    0.0f, 0.0f, -0.0f, -0.0f,\n    1.0f, std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity(),\n    1.0f, 1.0f,\n    std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    Atan2MaxAccSpecial,\n    ::atan2f,\n    atan2_max,\n    kAtan2MaxAccY,\n    kAtan2MaxAccX,\n    kAtan2Ulps)\n"
  },
  {
    "path": "tests/fast_math/atan_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <limits>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\n// We have reached asymptote for float32 at this value.\nconstexpr float kFarEnough = 20000000.0f;\n\nTEST(Atan, SpecialVals) {\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n\n  auto res = dfm::atan(-kFarEnough);\n  EXPECT_EQ(res, -kPi_2);\n  res = dfm::atan(kFarEnough);\n  EXPECT_EQ(res, kPi_2);\n  res = dfm::atan(0.0f);\n  EXPECT_EQ(res, 0.0f);\n  // NaN and Inf\n  EXPECT_NE(dfm::atan(kNaN), dfm::atan(kNaN));\n  EXPECT_EQ(dfm::atan(kInf), kPi_2);\n  EXPECT_EQ(dfm::atan(-kInf), -kPi_2);\n}\n\nTEST(Atan, Range) {\n  uint32_t ulps = dfm::evalAccuracy(atanf, dfm::atan<float>, -kFarEnough, kFarEnough);\n  EXPECT_LE(ulps, 3);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kAtanMaxUlps = 3;\nFAST_MATH_ACCURACY_TESTS(AtanAll, ::atanf, dfm::atan, -kFarEnough, kFarEnough, kAtanMaxUlps)\n\n// Special values tested across all SIMD backends.\nstatic const float kAtanSpecials[] = {\n    0.0f,\n    -0.0f,\n    -kFarEnough,\n    kFarEnough,\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    2.0f,\n    -2.0f,\n    10.0f,\n    -10.0f,\n    100.0f,\n    1e10f,\n    -1e10f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(AtanSpecial, ::atanf, dfm::atan, kAtanSpecials, kAtanMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/avx512_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <cmath>\n#include <limits>\n\n#include <gtest/gtest.h>\n\n#if defined(__AVX512F__)\n\nnamespace dfm = dispenso::fast_math;\nusing Avx512Float = dfm::Avx512Float;\nusing Avx512Int32 = dfm::Avx512Int32;\nusing Avx512Uint32 = dfm::Avx512Uint32;\nusing Avx512Mask = dfm::Avx512Mask;\n\nconstexpr int32_t kLanes = 16;\n\n// Helper: extract lane i from __m512.\nstatic float lane(__m512 v, int i) {\n  alignas(64) float buf[kLanes];\n  _mm512_store_ps(buf, v);\n  return buf[i];\n}\n\n// Helper: extract lane i from __m512i (as int32_t).\nstatic int32_t lane(__m512i v, int i) {\n  alignas(64) int32_t buf[kLanes];\n  _mm512_store_si512(buf, v);\n  return buf[i];\n}\n\n// Helper: extract bit i from Avx512Mask.\nstatic bool maskBit(Avx512Mask m, int i) {\n  return (m.m >> i) & 1;\n}\n\n// Helper: create __m512 from 16 distinct values.\nstatic __m512 make16(\n    float a,\n    float b,\n    float c,\n    float d,\n    float e,\n    float f,\n    float g,\n    float h,\n    float i,\n    float j,\n    float k,\n    float l,\n    float m,\n    float n,\n    float o,\n    float p) {\n  return _mm512_set_ps(p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a);\n}\n\n// ---- Avx512Mask basic operations ----\n\nTEST(Avx512Mask, ConstructFromInt) {\n  Avx512Mask allTrue(1);\n  EXPECT_EQ(allTrue.m, static_cast<__mmask16>(0xFFFF));\n  Avx512Mask allFalse(0);\n  EXPECT_EQ(allFalse.m, static_cast<__mmask16>(0));\n}\n\nTEST(Avx512Mask, LogicalOps) {\n  Avx512Mask a(static_cast<__mmask16>(0xFF00));\n  Avx512Mask b(static_cast<__mmask16>(0x0FF0));\n\n  Avx512Mask andResult = a & b;\n  EXPECT_EQ(andResult.m, static_cast<__mmask16>(0x0F00));\n\n  Avx512Mask orResult = a | b;\n  EXPECT_EQ(orResult.m, static_cast<__mmask16>(0xFFF0));\n\n  Avx512Mask xorResult = a ^ b;\n  EXPECT_EQ(xorResult.m, static_cast<__mmask16>(0xF0F0));\n\n  Avx512Mask notResult = !a;\n  EXPECT_EQ(notResult.m, static_cast<__mmask16>(0x00FF));\n}\n\nTEST(Avx512Mask, Equality) {\n  Avx512Mask a(static_cast<__mmask16>(0xFF00));\n  Avx512Mask b(static_cast<__mmask16>(0xFF00));\n  Avx512Mask c(static_cast<__mmask16>(0x00FF));\n\n  // Same masks → all bits set (per-bit XNOR)\n  Avx512Mask eqAB = a == b;\n  EXPECT_EQ(eqAB.m, static_cast<__mmask16>(0xFFFF));\n\n  // Complementary masks → all bits clear\n  Avx512Mask eqAC = a == c;\n  EXPECT_EQ(eqAC.m, static_cast<__mmask16>(0));\n\n  // mask == 0 is equivalent to !mask\n  Avx512Mask mask0 = a == Avx512Mask(0);\n  EXPECT_EQ(mask0.m, static_cast<__mmask16>(0x00FF));\n}\n\nTEST(Avx512Mask, ToInt32Conversion) {\n  Avx512Mask m(static_cast<__mmask16>(0xA5A5)); // 1010 0101 1010 0101\n  Avx512Int32 expanded = m; // implicit conversion\n  for (int i = 0; i < kLanes; ++i) {\n    int32_t expected = ((0xA5A5 >> i) & 1) ? -1 : 0;\n    EXPECT_EQ(lane(expanded, i), expected) << \"Lane \" << i;\n  }\n}\n\n// ---- Avx512Float basic arithmetic ----\n\nTEST(Avx512Float, Broadcast) {\n  Avx512Float v(3.0f);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(v, i), 3.0f);\n  }\n}\n\nTEST(Avx512Float, Arithmetic) {\n  Avx512Float a = make16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);\n  Avx512Float b = make16(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);\n\n  Avx512Float sum = a + b;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(sum, i), 17.0f) << \"Lane \" << i;\n  }\n\n  Avx512Float diff = b - a;\n  EXPECT_EQ(lane(diff, 0), 15.0f);\n  EXPECT_EQ(lane(diff, 15), -15.0f);\n\n  Avx512Float prod = a * b;\n  EXPECT_EQ(lane(prod, 0), 16.0f);\n  EXPECT_EQ(lane(prod, 7), 72.0f);\n  EXPECT_EQ(lane(prod, 15), 16.0f);\n\n  Avx512Float quot = a / b;\n  EXPECT_FLOAT_EQ(lane(quot, 0), 1.0f / 16.0f);\n  EXPECT_FLOAT_EQ(lane(quot, 15), 16.0f);\n}\n\nTEST(Avx512Float, Negation) {\n  Avx512Float a = make16(\n      1.0f,\n      -2.0f,\n      0.0f,\n      3.0f,\n      -0.5f,\n      100.0f,\n      -0.0f,\n      42.0f,\n      -1.0f,\n      2.0f,\n      0.0f,\n      -3.0f,\n      0.5f,\n      -100.0f,\n      0.0f,\n      -42.0f);\n  Avx512Float neg = -a;\n  EXPECT_EQ(lane(neg, 0), -1.0f);\n  EXPECT_EQ(lane(neg, 1), 2.0f);\n  EXPECT_EQ(lane(neg, 2), -0.0f);\n  EXPECT_EQ(lane(neg, 3), -3.0f);\n  EXPECT_EQ(lane(neg, 4), 0.5f);\n  EXPECT_EQ(lane(neg, 5), -100.0f);\n  // -(-0.0) should be +0.0\n  EXPECT_FALSE(std::signbit(lane(neg, 6)));\n  EXPECT_EQ(lane(neg, 7), -42.0f);\n}\n\nTEST(Avx512Float, CompoundAssignment) {\n  Avx512Float a(1.0f);\n  a += Avx512Float(2.0f);\n  EXPECT_EQ(lane(a, 0), 3.0f);\n  a -= Avx512Float(1.0f);\n  EXPECT_EQ(lane(a, 0), 2.0f);\n  a *= Avx512Float(5.0f);\n  EXPECT_EQ(lane(a, 0), 10.0f);\n}\n\n// ---- Avx512Float comparisons ----\n\nTEST(Avx512Float, Comparisons) {\n  Avx512Float a = make16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);\n  Avx512Float b = make16(2, 2, 1, 5, 5, 4, 7, 9, 9, 10, 11, 12, 13, 14, 15, 16);\n\n  Avx512Mask lt = a < b;\n  EXPECT_TRUE(maskBit(lt, 0)); // 1 < 2 true\n  EXPECT_FALSE(maskBit(lt, 1)); // 2 < 2 false\n  EXPECT_FALSE(maskBit(lt, 2)); // 3 < 1 false\n  EXPECT_TRUE(maskBit(lt, 3)); // 4 < 5 true\n  EXPECT_FALSE(maskBit(lt, 4)); // 5 < 5 false\n  EXPECT_FALSE(maskBit(lt, 5)); // 6 < 4 false\n  EXPECT_FALSE(maskBit(lt, 6)); // 7 < 7 false\n  EXPECT_TRUE(maskBit(lt, 7)); // 8 < 9 true\n\n  Avx512Mask gt = a > b;\n  EXPECT_FALSE(maskBit(gt, 0)); // 1 > 2 false\n  EXPECT_TRUE(maskBit(gt, 2)); // 3 > 1 true\n  EXPECT_TRUE(maskBit(gt, 5)); // 6 > 4 true\n\n  Avx512Mask eq = a == b;\n  EXPECT_FALSE(maskBit(eq, 0)); // 1 == 2 false\n  EXPECT_TRUE(maskBit(eq, 1)); // 2 == 2 true\n  EXPECT_TRUE(maskBit(eq, 4)); // 5 == 5 true\n  EXPECT_TRUE(maskBit(eq, 6)); // 7 == 7 true\n  // All lanes 8-15 are equal in our setup\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_TRUE(maskBit(eq, i)) << \"Lane \" << i;\n  }\n}\n\n// ---- Avx512Int32 arithmetic ----\n\nTEST(Avx512Int32, BasicOps) {\n  Avx512Int32 a(10);\n  Avx512Int32 b(3);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a + b, i), 13) << \"Lane \" << i;\n    EXPECT_EQ(lane(a - b, i), 7) << \"Lane \" << i;\n    EXPECT_EQ(lane(a * b, i), 30) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Int32, Negation) {\n  Avx512Int32 a =\n      Avx512Int32(_mm512_set_epi32(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));\n  Avx512Int32 neg = -a;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(neg, i), -(i + 1)) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Int32, ShiftOps) {\n  Avx512Int32 a(8);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a << 2, i), 32) << \"Lane \" << i;\n    EXPECT_EQ(lane(a >> 1, i), 4) << \"Lane \" << i;\n  }\n\n  Avx512Int32 neg(-8);\n  EXPECT_EQ(lane(neg >> 1, 0), -4); // Arithmetic shift preserves sign\n}\n\nTEST(Avx512Int32, Comparisons) {\n  Avx512Int32 a =\n      Avx512Int32(_mm512_set_epi32(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 5, 4, 3, 2, 1));\n  Avx512Int32 b =\n      Avx512Int32(_mm512_set_epi32(16, 15, 14, 13, 12, 11, 10, 9, 1, 7, 6, 4, 4, 3, 9, 0));\n\n  Avx512Mask eq = a == b;\n  EXPECT_FALSE(maskBit(eq, 0)); // 1 == 0 false\n  EXPECT_FALSE(maskBit(eq, 1)); // 2 == 9 false\n  EXPECT_TRUE(maskBit(eq, 2)); // 3 == 3 true\n  EXPECT_TRUE(maskBit(eq, 3)); // 4 == 4 true\n  EXPECT_FALSE(maskBit(eq, 4)); // 5 == 4 false\n  EXPECT_FALSE(maskBit(eq, 5)); // 5 == 6 false\n  EXPECT_TRUE(maskBit(eq, 6)); // 7 == 7 true\n  EXPECT_FALSE(maskBit(eq, 7)); // 8 == 1 false\n  // Lanes 8-15 are all equal\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_TRUE(maskBit(eq, i)) << \"Lane \" << i;\n  }\n\n  Avx512Mask lt = a < b;\n  EXPECT_FALSE(maskBit(lt, 0)); // 1 < 0 false\n  EXPECT_TRUE(maskBit(lt, 1)); // 2 < 9 true\n  EXPECT_TRUE(maskBit(lt, 5)); // 5 < 6 true\n}\n\n// ---- Avx512Uint32 ----\n\nTEST(Avx512Uint32, LogicalShift) {\n  Avx512Uint32 a(0x80000000u);\n  // Logical shift right — does NOT preserve sign.\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(static_cast<uint32_t>(lane(a >> 1, i)), 0x40000000u) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Uint32, UnsignedComparison) {\n  Avx512Uint32 a(0x80000000u);\n  Avx512Uint32 b(0x7FFFFFFFu);\n  // Unsigned: 0x80000000 > 0x7FFFFFFF (native AVX-512 unsigned compare)\n  Avx512Mask gt = a > b;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_TRUE(maskBit(gt, i)) << \"Lane \" << i;\n  }\n}\n\n// ---- bit_cast ----\n\nTEST(Avx512BitCast, FloatToInt) {\n  Avx512Float f(1.0f);\n  Avx512Int32 i = dfm::bit_cast<Avx512Int32>(f);\n  for (int j = 0; j < kLanes; ++j) {\n    EXPECT_EQ(lane(i, j), 0x3f800000) << \"Lane \" << j;\n  }\n}\n\nTEST(Avx512BitCast, IntToFloat) {\n  Avx512Int32 i(0x40000000);\n  Avx512Float f = dfm::bit_cast<Avx512Float>(i);\n  for (int j = 0; j < kLanes; ++j) {\n    EXPECT_EQ(lane(f, j), 2.0f) << \"Lane \" << j;\n  }\n}\n\nTEST(Avx512BitCast, RoundTrip) {\n  Avx512Float original = make16(\n      1.0f,\n      -2.0f,\n      0.5f,\n      42.0f,\n      -0.0f,\n      3.14f,\n      1e10f,\n      -1e-10f,\n      0.0f,\n      -1.0f,\n      2.0f,\n      -0.5f,\n      100.0f,\n      -100.0f,\n      1e-30f,\n      -1e30f);\n  Avx512Float roundtripped = dfm::bit_cast<Avx512Float>(dfm::bit_cast<Avx512Int32>(original));\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(roundtripped, i), lane(original, i)) << \"Lane \" << i;\n  }\n}\n\n// ---- FloatTraits<Avx512Float> ----\n\nTEST(Avx512FloatTraits, ConditionalWithMask) {\n  // Create mask: even lanes true, odd lanes false\n  Avx512Mask mask(static_cast<__mmask16>(0x5555)); // 0101 0101 0101 0101\n  Avx512Float x(10.0f);\n  Avx512Float y(20.0f);\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::conditional(mask, x, y);\n  for (int i = 0; i < kLanes; ++i) {\n    float expected = (i % 2 == 0) ? 10.0f : 20.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, ConditionalFromComparison) {\n  // Test that comparison → mask → conditional works end-to-end.\n  Avx512Float a = make16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);\n  Avx512Float threshold(8.5f);\n  auto mask = a > threshold;\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::conditional(mask, Avx512Float(100.0f), a);\n  for (int i = 0; i < kLanes; ++i) {\n    float inp = static_cast<float>(i + 1);\n    float expected = (inp > 8.5f) ? 100.0f : inp;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, ConditionalInt32WithMask) {\n  Avx512Mask mask(static_cast<__mmask16>(0x5555));\n  Avx512Int32 x(100);\n  Avx512Int32 y(200);\n  Avx512Int32 result = dfm::FloatTraits<Avx512Float>::conditional(mask, x, y);\n  for (int i = 0; i < kLanes; ++i) {\n    int32_t expected = (i % 2 == 0) ? 100 : 200;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, ConditionalWithLaneWideMask) {\n  // _mm512_set_epi32 fills from highest to lowest lane: lane 0=0, lane 1=-1, etc.\n  // So odd lanes have mask=-1 (true → x), even lanes have mask=0 (false → y).\n  Avx512Int32 mask =\n      Avx512Int32(_mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0));\n  Avx512Float x(10.0f);\n  Avx512Float y(20.0f);\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::conditional(mask, x, y);\n  for (int i = 0; i < kLanes; ++i) {\n    float expected = (i % 2 == 0) ? 20.0f : 10.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, Apply) {\n  Avx512Mask mask(static_cast<__mmask16>(0xFF00)); // upper 8 lanes true\n  Avx512Float x(42.0f);\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::apply(mask, x);\n  for (int i = 0; i < 8; ++i) {\n    EXPECT_EQ(lane(result, i), 0.0f) << \"Lane \" << i;\n  }\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 42.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, Fma) {\n  Avx512Float a(2.0f), b(3.0f), c(4.0f);\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::fma(a, b, c);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 10.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, Sqrt) {\n  Avx512Float input = make16(\n      1.0f,\n      4.0f,\n      9.0f,\n      16.0f,\n      25.0f,\n      36.0f,\n      49.0f,\n      64.0f,\n      81.0f,\n      100.0f,\n      121.0f,\n      144.0f,\n      169.0f,\n      196.0f,\n      225.0f,\n      256.0f);\n  Avx512Float result = dfm::FloatTraits<Avx512Float>::sqrt(input);\n  for (int i = 0; i < kLanes; ++i) {\n    float expected = std::sqrt(lane(input, i));\n    EXPECT_FLOAT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512FloatTraits, MinMax) {\n  Avx512Float a = make16(1, 5, 3, 7, 2, 8, 4, 6, 10, 0, 9, 1, 11, 3, 7, 5);\n  Avx512Float b = make16(4, 2, 6, 0, 9, 1, 4, 3, 0, 10, 1, 9, 3, 11, 5, 7);\n  Avx512Float mn = dfm::FloatTraits<Avx512Float>::min(a, b);\n  Avx512Float mx = dfm::FloatTraits<Avx512Float>::max(a, b);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(mn, i), std::min(lane(a, i), lane(b, i))) << \"Lane \" << i;\n    EXPECT_EQ(lane(mx, i), std::max(lane(a, i), lane(b, i))) << \"Lane \" << i;\n  }\n}\n\n// ---- Util functions ----\n\nTEST(Avx512Util, FloorSmall) {\n  __m512 x = make16(\n      1.5f,\n      -1.5f,\n      2.0f,\n      0.1f,\n      3.9f,\n      -0.1f,\n      0.0f,\n      -3.7f,\n      100.1f,\n      -100.9f,\n      0.999f,\n      -0.999f,\n      10.0f,\n      -10.0f,\n      0.5f,\n      -0.5f);\n  __m512 result = dfm::floor_small(x);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), std::floor(lane(x, i))) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, ConvertToInt) {\n  __m512 x = make16(\n      1.6f,\n      -1.6f,\n      2.5f,\n      0.4f,\n      3.5f,\n      -2.5f,\n      0.0f,\n      100.0f,\n      -100.0f,\n      1.5f,\n      -1.5f,\n      10.4f,\n      -10.4f,\n      0.5f,\n      -0.5f,\n      42.0f);\n  __m512i result = dfm::convert_to_int(x);\n  // Round to nearest even.\n  int32_t expected[] = {2, -2, 2, 0, 4, -2, 0, 100, -100, 2, -2, 10, -10, 0, 0, 42};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, ConvertToInt_NaN) {\n  // NaN/Inf should be masked to 0.\n  __m512 x = make16(\n      std::numeric_limits<float>::quiet_NaN(),\n      std::numeric_limits<float>::infinity(),\n      -std::numeric_limits<float>::infinity(),\n      1.0f,\n      2.0f,\n      3.0f,\n      4.0f,\n      5.0f,\n      6.0f,\n      7.0f,\n      8.0f,\n      9.0f,\n      10.0f,\n      11.0f,\n      12.0f,\n      13.0f);\n  __m512i result = dfm::convert_to_int(x);\n  EXPECT_EQ(lane(result, 0), 0); // NaN → 0\n  EXPECT_EQ(lane(result, 1), 0); // Inf → 0\n  EXPECT_EQ(lane(result, 2), 0); // -Inf → 0\n  EXPECT_EQ(lane(result, 3), 1);\n}\n\nTEST(Avx512Util, Gather) {\n  float table[] = {\n      10.0f,\n      20.0f,\n      30.0f,\n      40.0f,\n      50.0f,\n      60.0f,\n      70.0f,\n      80.0f,\n      90.0f,\n      100.0f,\n      110.0f,\n      120.0f,\n      130.0f,\n      140.0f,\n      150.0f,\n      160.0f,\n      170.0f};\n  __m512i indices = _mm512_set_epi32(16, 0, 15, 1, 14, 2, 13, 3, 12, 4, 11, 5, 10, 6, 9, 7);\n  __m512 result = dfm::gather<Avx512Float>(table, indices);\n  int32_t idx_vals[] = {7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 0, 16};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), table[idx_vals[i]]) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, IntDivBy3) {\n  __m512i a = _mm512_set_epi32(99, 90, 81, 72, 63, 48, 33, 30, 27, 24, 21, 12, 9, 6, 3, 0);\n  __m512i result = dfm::int_div_by_3(a);\n  int32_t inputs[] = {0, 3, 6, 9, 12, 21, 24, 27, 30, 33, 48, 63, 72, 81, 90, 99};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), inputs[i] / 3) << \"Lane \" << i << \" input=\" << inputs[i];\n  }\n}\n\nTEST(Avx512Util, Signof) {\n  __m512 x = make16(\n      1.0f,\n      -1.0f,\n      0.0f,\n      -0.0f,\n      42.0f,\n      -42.0f,\n      0.5f,\n      -0.5f,\n      1e10f,\n      -1e10f,\n      1e-20f,\n      -1e-10f,\n      100.0f,\n      -100.0f,\n      0.001f,\n      -0.001f);\n  __m512 result = dfm::signof(x);\n  for (int i = 0; i < kLanes; ++i) {\n    float expected = std::signbit(lane(x, i)) ? -1.0f : 1.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, Signofi) {\n  __m512i a = _mm512_set_epi32(-100, 100, -1, 0, 10, -5, 1, -1, 50, -50, 0, -0, 1000, -1000, 7, -7);\n  __m512i result = dfm::signofi<Avx512Float>(Avx512Int32(a));\n  int32_t inputs[16];\n  alignas(64) int32_t buf[16];\n  _mm512_store_si512(buf, a);\n  for (int i = 0; i < kLanes; ++i) {\n    inputs[i] = buf[i];\n    int32_t expected = (inputs[i] < 0) ? -1 : 1;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i << \" input=\" << inputs[i];\n  }\n}\n\nTEST(Avx512Util, Nonnormal) {\n  __m512 x = make16(\n      1.0f,\n      std::numeric_limits<float>::infinity(),\n      -std::numeric_limits<float>::infinity(),\n      std::numeric_limits<float>::quiet_NaN(),\n      0.0f,\n      -0.0f,\n      std::numeric_limits<float>::denorm_min(),\n      std::numeric_limits<float>::max(),\n      std::numeric_limits<float>::min(),\n      -1.0f,\n      42.0f,\n      -42.0f,\n      0.5f,\n      -0.5f,\n      1e30f,\n      -1e30f);\n  Avx512Mask result = dfm::nonnormal(Avx512Float(x));\n  EXPECT_FALSE(maskBit(result, 0)); // normal\n  EXPECT_TRUE(maskBit(result, 1)); // inf\n  EXPECT_TRUE(maskBit(result, 2)); // -inf\n  EXPECT_TRUE(maskBit(result, 3)); // nan\n  EXPECT_FALSE(maskBit(result, 4)); // zero\n  EXPECT_FALSE(maskBit(result, 5)); // -zero\n  EXPECT_FALSE(maskBit(result, 6)); // denorm\n  EXPECT_FALSE(maskBit(result, 7)); // normal max\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_FALSE(maskBit(result, i)) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, NonnormalOrZero) {\n  __m512 x = make16(\n      1.0f,\n      std::numeric_limits<float>::infinity(),\n      -std::numeric_limits<float>::infinity(),\n      std::numeric_limits<float>::quiet_NaN(),\n      0.0f,\n      -0.0f,\n      std::numeric_limits<float>::denorm_min(),\n      std::numeric_limits<float>::max(),\n      std::numeric_limits<float>::min(),\n      -1.0f,\n      42.0f,\n      -42.0f,\n      0.5f,\n      -0.5f,\n      1e30f,\n      -1e30f);\n  Avx512Mask result = dfm::nonnormalOrZero(dfm::bit_cast<Avx512Int32>(Avx512Float(x)));\n  EXPECT_FALSE(maskBit(result, 0)); // normal\n  EXPECT_TRUE(maskBit(result, 1)); // inf\n  EXPECT_TRUE(maskBit(result, 2)); // -inf\n  EXPECT_TRUE(maskBit(result, 3)); // nan\n  EXPECT_TRUE(maskBit(result, 4)); // zero\n  EXPECT_TRUE(maskBit(result, 5)); // -zero (exponent bits are zero)\n  EXPECT_TRUE(maskBit(result, 6)); // denorm (exponent bits are zero)\n  EXPECT_FALSE(maskBit(result, 7)); // normal max\n}\n\nTEST(Avx512Util, BoolAsOne) {\n  Avx512Mask mask(static_cast<__mmask16>(0x5555)); // even lanes true\n  Avx512Float fResult = dfm::bool_as_one<Avx512Float>(mask);\n  Avx512Int32 iResult = dfm::bool_as_one<Avx512Int32>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    float expectedF = (i % 2 == 0) ? 1.0f : 0.0f;\n    int32_t expectedI = (i % 2 == 0) ? 1 : 0;\n    EXPECT_EQ(lane(fResult, i), expectedF) << \"Lane \" << i;\n    EXPECT_EQ(lane(iResult, i), expectedI) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, NboolAsOne) {\n  Avx512Mask mask(static_cast<__mmask16>(0x5555)); // even lanes true\n  Avx512Float fResult = dfm::nbool_as_one<Avx512Float>(mask);\n  Avx512Int32 iResult = dfm::nbool_as_one<Avx512Int32>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    float expectedF = (i % 2 == 0) ? 0.0f : 1.0f;\n    int32_t expectedI = (i % 2 == 0) ? 0 : 1;\n    EXPECT_EQ(lane(fResult, i), expectedF) << \"Lane \" << i;\n    EXPECT_EQ(lane(iResult, i), expectedI) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, BoolAsMask) {\n  Avx512Mask mask(static_cast<__mmask16>(0xA5A5));\n  Avx512Int32 intMask = dfm::bool_as_mask<Avx512Int32>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    int32_t expected = maskBit(mask, i) ? -1 : 0;\n    EXPECT_EQ(lane(intMask, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(Avx512Util, BoolApplyOrZero) {\n  Avx512Mask mask(static_cast<__mmask16>(0xFF00)); // upper 8 lanes true\n  Avx512Float val(42.0f);\n  Avx512Float result = dfm::bool_apply_or_zero(mask, val);\n  for (int i = 0; i < 8; ++i) {\n    EXPECT_EQ(lane(result, i), 0.0f) << \"Lane \" << i;\n  }\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 42.0f) << \"Lane \" << i;\n  }\n\n  // Test with int\n  Avx512Int32 ival(0x7f800000);\n  Avx512Int32 iresult = dfm::bool_apply_or_zero(mask, ival);\n  for (int i = 0; i < 8; ++i) {\n    EXPECT_EQ(lane(iresult, i), 0) << \"Lane \" << i;\n  }\n  for (int i = 8; i < kLanes; ++i) {\n    EXPECT_EQ(lane(iresult, i), 0x7f800000) << \"Lane \" << i;\n  }\n}\n\n#else // !defined(__AVX512F__)\n\nTEST(Avx512, Unavailable) {\n  GTEST_SKIP() << \"AVX-512 not available\";\n}\n\n#endif // defined(__AVX512F__)\n"
  },
  {
    "path": "tests/fast_math/avx_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <cmath>\n#include <limits>\n\n#include <gtest/gtest.h>\n\n#if defined(__AVX2__)\n\nnamespace dfm = dispenso::fast_math;\nusing AvxFloat = dfm::AvxFloat;\nusing AvxInt32 = dfm::AvxInt32;\nusing AvxUint32 = dfm::AvxUint32;\n\nconstexpr int32_t kLanes = 8;\n\n// Helper: extract lane i from __m256.\nstatic float lane(__m256 v, int i) {\n  alignas(32) float buf[kLanes];\n  _mm256_store_ps(buf, v);\n  return buf[i];\n}\n\n// Helper: extract lane i from __m256i (as int32_t).\nstatic int32_t lane(__m256i v, int i) {\n  alignas(32) int32_t buf[kLanes];\n  _mm256_store_si256(reinterpret_cast<__m256i*>(buf), v);\n  return buf[i];\n}\n\n// Helper: create __m256 from 8 distinct values.\nstatic __m256 make8(float a, float b, float c, float d, float e, float f, float g, float h) {\n  return _mm256_set_ps(h, g, f, e, d, c, b, a);\n}\n\n// ---- AvxFloat basic arithmetic ----\n\nTEST(AvxFloat, Broadcast) {\n  AvxFloat v(3.0f);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(v, i), 3.0f);\n  }\n}\n\nTEST(AvxFloat, Arithmetic) {\n  AvxFloat a = make8(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);\n  AvxFloat b = make8(8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f);\n\n  AvxFloat sum = a + b;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(sum, i), 9.0f) << \"Lane \" << i;\n  }\n\n  AvxFloat diff = b - a;\n  EXPECT_EQ(lane(diff, 0), 7.0f);\n  EXPECT_EQ(lane(diff, 7), -7.0f);\n\n  AvxFloat prod = a * b;\n  EXPECT_EQ(lane(prod, 0), 8.0f);\n  EXPECT_EQ(lane(prod, 3), 20.0f);\n  EXPECT_EQ(lane(prod, 7), 8.0f);\n\n  AvxFloat quot = a / b;\n  EXPECT_FLOAT_EQ(lane(quot, 0), 0.125f);\n  EXPECT_FLOAT_EQ(lane(quot, 7), 8.0f);\n}\n\nTEST(AvxFloat, Negation) {\n  AvxFloat a = make8(1.0f, -2.0f, 0.0f, 3.0f, -0.5f, 100.0f, -0.0f, 42.0f);\n  AvxFloat neg = -a;\n  EXPECT_EQ(lane(neg, 0), -1.0f);\n  EXPECT_EQ(lane(neg, 1), 2.0f);\n  EXPECT_EQ(lane(neg, 2), -0.0f);\n  EXPECT_EQ(lane(neg, 3), -3.0f);\n  EXPECT_EQ(lane(neg, 4), 0.5f);\n  EXPECT_EQ(lane(neg, 5), -100.0f);\n  // -(-0.0) should be +0.0\n  EXPECT_FALSE(std::signbit(lane(neg, 6)));\n  EXPECT_EQ(lane(neg, 7), -42.0f);\n}\n\nTEST(AvxFloat, CompoundAssignment) {\n  AvxFloat a(1.0f);\n  a += AvxFloat(2.0f);\n  EXPECT_EQ(lane(a, 0), 3.0f);\n  a -= AvxFloat(1.0f);\n  EXPECT_EQ(lane(a, 0), 2.0f);\n  a *= AvxFloat(5.0f);\n  EXPECT_EQ(lane(a, 0), 10.0f);\n}\n\n// ---- AvxFloat comparisons ----\n\nTEST(AvxFloat, Comparisons) {\n  AvxFloat a = make8(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);\n  AvxFloat b = make8(2.0f, 2.0f, 1.0f, 5.0f, 5.0f, 4.0f, 7.0f, 9.0f);\n\n  AvxFloat lt = a < b;\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, 0)), 0u); // 1 < 2 true\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 1)), 0u); // 2 < 2 false\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 2)), 0u); // 3 < 1 false\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, 3)), 0u); // 4 < 5 true\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 4)), 0u); // 5 < 5 false\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 5)), 0u); // 6 < 4 false\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 6)), 0u); // 7 < 7 false\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, 7)), 0u); // 8 < 9 true\n\n  AvxFloat gt = a > b;\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(gt, 0)), 0u); // 1 > 2 false\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(gt, 2)), 0u); // 3 > 1 true\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(gt, 5)), 0u); // 6 > 4 true\n\n  AvxFloat eq = a == b;\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(eq, 0)), 0u); // 1 == 2 false\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(eq, 1)), 0u); // 2 == 2 true\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(eq, 4)), 0u); // 5 == 5 true\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(eq, 6)), 0u); // 7 == 7 true\n}\n\nTEST(AvxFloat, LogicalNot) {\n  AvxFloat mask = AvxFloat(make8(1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f)) > AvxFloat(0.5f);\n  AvxFloat notmask = !mask;\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(notmask, 0)), 0u);\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(notmask, 1)), 0u);\n}\n\n// ---- AvxInt32 arithmetic ----\n\nTEST(AvxInt32, BasicOps) {\n  AvxInt32 a(10);\n  AvxInt32 b(3);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a + b, i), 13) << \"Lane \" << i;\n    EXPECT_EQ(lane(a - b, i), 7) << \"Lane \" << i;\n    EXPECT_EQ(lane(a * b, i), 30) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxInt32, Negation) {\n  AvxInt32 a = AvxInt32(_mm256_set_epi32(8, 7, 6, 5, 4, 3, 2, 1));\n  AvxInt32 neg = -a;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(neg, i), -(i + 1)) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxInt32, ShiftOps) {\n  AvxInt32 a(8);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a << 2, i), 32) << \"Lane \" << i;\n    EXPECT_EQ(lane(a >> 1, i), 4) << \"Lane \" << i;\n  }\n\n  AvxInt32 neg(-8);\n  EXPECT_EQ(lane(neg >> 1, 0), -4); // Arithmetic shift preserves sign\n}\n\nTEST(AvxInt32, Comparisons) {\n  AvxInt32 a = AvxInt32(_mm256_set_epi32(8, 7, 5, 5, 4, 3, 2, 1));\n  AvxInt32 b = AvxInt32(_mm256_set_epi32(1, 7, 6, 4, 4, 3, 9, 0));\n\n  AvxInt32 eq = a == b;\n  EXPECT_EQ(lane(eq, 0), 0); // 1 == 0 false\n  EXPECT_NE(lane(eq, 2), 0); // 3 == 3 true\n  EXPECT_NE(lane(eq, 3), 0); // 4 == 4 true\n  EXPECT_NE(lane(eq, 6), 0); // 7 == 7 true\n\n  AvxInt32 lt = a < b;\n  EXPECT_EQ(lane(lt, 0), 0); // 1 < 0 false\n  EXPECT_NE(lane(lt, 1), 0); // 2 < 9 true\n}\n\n// ---- AvxUint32 ----\n\nTEST(AvxUint32, LogicalShift) {\n  AvxUint32 a(0x80000000u);\n  // Logical shift right — does NOT preserve sign.\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(static_cast<uint32_t>(lane(a >> 1, i)), 0x40000000u) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUint32, UnsignedComparison) {\n  AvxUint32 a(0x80000000u);\n  AvxUint32 b(0x7FFFFFFFu);\n  // Unsigned: 0x80000000 > 0x7FFFFFFF\n  AvxUint32 gt = a > b;\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_NE(static_cast<uint32_t>(lane(gt, i)), 0u) << \"Lane \" << i;\n  }\n}\n\n// ---- bit_cast ----\n\nTEST(AvxBitCast, FloatToInt) {\n  AvxFloat f(1.0f);\n  AvxInt32 i = dfm::bit_cast<AvxInt32>(f);\n  for (int j = 0; j < kLanes; ++j) {\n    EXPECT_EQ(lane(i, j), 0x3f800000) << \"Lane \" << j;\n  }\n}\n\nTEST(AvxBitCast, IntToFloat) {\n  AvxInt32 i(0x40000000);\n  AvxFloat f = dfm::bit_cast<AvxFloat>(i);\n  for (int j = 0; j < kLanes; ++j) {\n    EXPECT_EQ(lane(f, j), 2.0f) << \"Lane \" << j;\n  }\n}\n\nTEST(AvxBitCast, RoundTrip) {\n  AvxFloat original = make8(1.0f, -2.0f, 0.5f, 42.0f, -0.0f, 3.14f, 1e10f, -1e-10f);\n  AvxFloat roundtripped = dfm::bit_cast<AvxFloat>(dfm::bit_cast<AvxInt32>(original));\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(roundtripped, i), lane(original, i)) << \"Lane \" << i;\n  }\n}\n\n// ---- FloatTraits<AvxFloat> ----\n\nTEST(AvxFloatTraits, Conditional) {\n  AvxFloat mask = AvxFloat(make8(1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f)) > AvxFloat(0.5f);\n  AvxFloat x(10.0f);\n  AvxFloat y(20.0f);\n  AvxFloat result = dfm::FloatTraits<AvxFloat>::conditional(mask, x, y);\n  for (int i = 0; i < kLanes; ++i) {\n    float expected = (i % 2 == 0) ? 10.0f : 20.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxFloatTraits, ConditionalInt32) {\n  AvxFloat mask = AvxFloat(make8(1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f)) > AvxFloat(0.5f);\n  AvxInt32 x(100);\n  AvxInt32 y(200);\n  AvxInt32 result = dfm::FloatTraits<AvxFloat>::conditional(mask, x, y);\n  for (int i = 0; i < kLanes; ++i) {\n    int32_t expected = (i % 2 == 0) ? 100 : 200;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxFloatTraits, Fma) {\n  AvxFloat a(2.0f), b(3.0f), c(4.0f);\n  AvxFloat result = dfm::FloatTraits<AvxFloat>::fma(a, b, c);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 10.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxFloatTraits, Sqrt) {\n  AvxFloat input = make8(1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 36.0f, 49.0f, 64.0f);\n  AvxFloat result = dfm::FloatTraits<AvxFloat>::sqrt(input);\n  float expected[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_FLOAT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxFloatTraits, MinMax) {\n  AvxFloat a = make8(1.0f, 5.0f, 3.0f, 7.0f, 2.0f, 8.0f, 4.0f, 6.0f);\n  AvxFloat b = make8(4.0f, 2.0f, 6.0f, 0.0f, 9.0f, 1.0f, 4.0f, 3.0f);\n  AvxFloat mn = dfm::FloatTraits<AvxFloat>::min(a, b);\n  AvxFloat mx = dfm::FloatTraits<AvxFloat>::max(a, b);\n  float emin[] = {1.0f, 2.0f, 3.0f, 0.0f, 2.0f, 1.0f, 4.0f, 3.0f};\n  float emax[] = {4.0f, 5.0f, 6.0f, 7.0f, 9.0f, 8.0f, 4.0f, 6.0f};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(mn, i), emin[i]) << \"Lane \" << i;\n    EXPECT_EQ(lane(mx, i), emax[i]) << \"Lane \" << i;\n  }\n}\n\n// ---- Util functions ----\n\nTEST(AvxUtil, FloorSmall) {\n  __m256 x = make8(1.5f, -1.5f, 2.0f, 0.1f, 3.9f, -0.1f, 0.0f, -3.7f);\n  __m256 result = dfm::floor_small(x);\n  float expected[] = {1.0f, -2.0f, 2.0f, 0.0f, 3.0f, -1.0f, 0.0f, -4.0f};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUtil, ConvertToInt) {\n  __m256 x = make8(1.6f, -1.6f, 2.5f, 0.4f, 3.5f, -2.5f, 0.0f, 100.0f);\n  __m256i result = dfm::convert_to_int(x);\n  // Round to nearest even.\n  int32_t expected[] = {2, -2, 2, 0, 4, -2, 0, 100};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUtil, ConvertToInt_NaN) {\n  // NaN/Inf should be masked to 0.\n  __m256 x = make8(\n      std::numeric_limits<float>::quiet_NaN(),\n      std::numeric_limits<float>::infinity(),\n      -std::numeric_limits<float>::infinity(),\n      1.0f,\n      2.0f,\n      3.0f,\n      4.0f,\n      5.0f);\n  __m256i result = dfm::convert_to_int(x);\n  EXPECT_EQ(lane(result, 0), 0); // NaN → 0\n  EXPECT_EQ(lane(result, 1), 0); // Inf → 0\n  EXPECT_EQ(lane(result, 2), 0); // -Inf → 0\n  EXPECT_EQ(lane(result, 3), 1);\n}\n\nTEST(AvxUtil, Gather) {\n  float table[] = {10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f};\n  __m256i indices = _mm256_set_epi32(8, 0, 5, 2, 7, 1, 4, 3);\n  __m256 result = dfm::gather<AvxFloat>(table, indices);\n  EXPECT_EQ(lane(result, 0), 40.0f);\n  EXPECT_EQ(lane(result, 1), 50.0f);\n  EXPECT_EQ(lane(result, 2), 20.0f);\n  EXPECT_EQ(lane(result, 3), 80.0f);\n  EXPECT_EQ(lane(result, 4), 30.0f);\n  EXPECT_EQ(lane(result, 5), 60.0f);\n  EXPECT_EQ(lane(result, 6), 10.0f);\n  EXPECT_EQ(lane(result, 7), 90.0f);\n}\n\nTEST(AvxUtil, IntDivBy3) {\n  __m256i a = _mm256_set_epi32(99, 30, 27, 12, 9, 6, 3, 0);\n  __m256i result = dfm::int_div_by_3(a);\n  int32_t expected[] = {0, 1, 2, 3, 4, 9, 10, 33};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUtil, Signof) {\n  __m256 x = make8(1.0f, -1.0f, 0.0f, -0.0f, 42.0f, -42.0f, 0.5f, -0.5f);\n  __m256 result = dfm::signof(x);\n  float expected[] = {1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUtil, Signofi) {\n  __m256i a = _mm256_set_epi32(-100, 100, -1, 0, 10, -5, 1, -1);\n  __m256i result = dfm::signofi<AvxFloat>(AvxInt32(a));\n  int32_t expected[] = {-1, 1, -1, 1, 1, -1, 1, -1};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), expected[i]) << \"Lane \" << i;\n  }\n}\n\nTEST(AvxUtil, Nonnormal) {\n  __m256 x = make8(\n      1.0f,\n      std::numeric_limits<float>::infinity(),\n      -std::numeric_limits<float>::infinity(),\n      std::numeric_limits<float>::quiet_NaN(),\n      0.0f,\n      -0.0f,\n      std::numeric_limits<float>::denorm_min(),\n      std::numeric_limits<float>::max());\n  AvxInt32 result = dfm::nonnormal(AvxFloat(x));\n  EXPECT_EQ(lane(result, 0), 0); // normal\n  EXPECT_NE(lane(result, 1), 0); // inf\n  EXPECT_NE(lane(result, 2), 0); // -inf\n  EXPECT_NE(lane(result, 3), 0); // nan\n  EXPECT_EQ(lane(result, 4), 0); // zero\n  EXPECT_EQ(lane(result, 5), 0); // -zero\n  EXPECT_EQ(lane(result, 6), 0); // denorm\n  EXPECT_EQ(lane(result, 7), 0); // normal max\n}\n\n#else // !defined(__AVX2__)\n\n// Dummy test so the binary has at least one test on non-AVX2 platforms.\nTEST(AvxFloat, NotAvailable) {\n  GTEST_SKIP() << \"AVX2 not available\";\n}\n\n#endif // defined(__AVX2__)\n"
  },
  {
    "path": "tests/fast_math/bivariate_ulp_eval.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Reusable harness for exhaustive ULP evaluation of two-argument fast_math\n// functions. Uses Halton low-discrepancy sequences for uniform 2D domain\n// coverage and dispenso::parallel_for for parallel evaluation.\n//\n// Usage pattern (in a per-function *_ulp_eval.cpp):\n//\n//   #include \"bivariate_ulp_eval.h\"\n//\n//   // Define ground truth, domains, and batch runners (scalar + SIMD).\n//   // Call evalFunc2D() for each variant.\n//\n// The batch runner interface:\n//   void runner(const float* xs, const float* ys, float* out, int32_t n);\n// n is always a multiple of kBatchSize (64). Scalar runners process one\n// element at a time; SIMD runners process kLanes at a time (4/8/16).\n\n#pragma once\n\n#include <atomic>\n#include <cmath>\n#include <cstdint>\n#include <cstdio>\n#include <cstring>\n\n#include <dispenso/parallel_for.h>\n\n#include <dispenso/fast_math/util.h>\n\nnamespace dispenso {\nnamespace fast_math {\n\n// --- Halton sequence ---\n\n// Compute element i of the Halton sequence in base b. Returns [0, 1).\ninline double halton(uint64_t i, uint32_t b) {\n  double f = 1.0;\n  double r = 0.0;\n  uint64_t idx = i;\n  while (idx > 0) {\n    f /= static_cast<double>(b);\n    r += f * static_cast<double>(idx % b);\n    idx /= b;\n  }\n  return r;\n}\n\n// Map a Halton value in [0, 1) to [lo, hi]. Uses log-space mapping when the\n// range spans >100x (better coverage of both small and large values).\ninline float mapToRange(double h, float lo, float hi) {\n  if (lo > 0.0f && hi / lo > 100.0f) {\n    double log_lo = std::log(static_cast<double>(lo));\n    double log_hi = std::log(static_cast<double>(hi));\n    return static_cast<float>(std::exp(log_lo + h * (log_hi - log_lo)));\n  }\n  return static_cast<float>(static_cast<double>(lo) + h * (static_cast<double>(hi) - lo));\n}\n\n// --- Types ---\n\nstruct Domain2D {\n  float x_lo, x_hi;\n  float y_lo, y_hi;\n  const char* label;\n};\n\nstruct EvalResult2D {\n  uint32_t maxUlp;\n  float worstX;\n  float worstY;\n  uint64_t count3; // samples with >= 3 ULP error\n  uint64_t validSamples;\n};\n\nusing GroundTruth2D = float (*)(float, float);\n\n// Batch size for Halton sample generation. Must be a multiple of the widest\n// SIMD width (64 bytes / 4 bytes = 16 lanes for AVX-512). 64 gives 4 full\n// AVX-512 vectors per batch.\nstatic constexpr int32_t kBatchSize = 64;\n\n// --- Core evaluation ---\n\n// Evaluate a two-argument function over a 2D domain using Halton sampling.\n// gt: ground truth function (double-precision internally).\n// runner: batch processor — processes kBatchSize (x,y) pairs from aligned arrays.\n// domain: 2D domain to sample.\n// numSamples: total number of Halton samples.\ntemplate <typename BatchRunner>\nEvalResult2D\nevalDomain2D(GroundTruth2D gt, BatchRunner runner, const Domain2D& domain, uint64_t numSamples) {\n  // Round up to multiple of kBatchSize for clean batch processing.\n  uint64_t numBatches = (numSamples + kBatchSize - 1) / kBatchSize;\n\n  std::atomic<uint32_t> globalMaxUlp{0};\n  std::atomic<float> globalWorstX{0.0f};\n  std::atomic<float> globalWorstY{0.0f};\n  std::atomic<uint64_t> globalCount3{0};\n  std::atomic<uint64_t> globalValid{0};\n\n  dispenso::parallel_for(\n      dispenso::makeChunkedRange(uint64_t{0}, numBatches, uint64_t{256}),\n      [&](uint64_t batchBegin, uint64_t batchEnd) {\n        alignas(64) float xs[kBatchSize];\n        alignas(64) float ys[kBatchSize];\n        alignas(64) float results[kBatchSize];\n\n        uint32_t localMax = 0;\n        float localWorstX = 0.0f;\n        float localWorstY = 0.0f;\n        uint64_t localCount3 = 0;\n        uint64_t localValid = 0;\n\n        for (uint64_t bi = batchBegin; bi < batchEnd; ++bi) {\n          uint64_t sampleBase = bi * kBatchSize;\n\n          // Generate Halton samples for this batch.\n          int32_t batchN = static_cast<int32_t>(\n              std::min(static_cast<uint64_t>(kBatchSize), numSamples - sampleBase));\n          for (int32_t j = 0; j < batchN; ++j) {\n            uint64_t idx = sampleBase + static_cast<uint64_t>(j) + 1; // +1: skip degenerate i=0\n            xs[j] = mapToRange(halton(idx, 2), domain.x_lo, domain.x_hi);\n            ys[j] = mapToRange(halton(idx, 3), domain.y_lo, domain.y_hi);\n          }\n          // Pad remainder with safe values (won't be compared).\n          for (int32_t j = batchN; j < kBatchSize; ++j) {\n            xs[j] = domain.x_lo;\n            ys[j] = domain.y_lo;\n          }\n\n          // Run approximation on full batch (SIMD needs aligned, full-width loads).\n          runner(xs, ys, results, kBatchSize);\n\n          // Compare only the real samples against ground truth.\n          for (int32_t j = 0; j < batchN; ++j) {\n            float g = gt(xs[j], ys[j]);\n            float a = results[j];\n\n            if (!std::isfinite(g) || g == 0.0f || !std::isfinite(a))\n              continue;\n\n            ++localValid;\n            uint32_t d = float_distance(g, a);\n            if (d >= 3)\n              ++localCount3;\n            if (d > localMax) {\n              localMax = d;\n              localWorstX = xs[j];\n              localWorstY = ys[j];\n            }\n          }\n        }\n\n        globalCount3.fetch_add(localCount3, std::memory_order_relaxed);\n        globalValid.fetch_add(localValid, std::memory_order_relaxed);\n        uint32_t prev = globalMaxUlp.load(std::memory_order_relaxed);\n        while (localMax > prev) {\n          if (globalMaxUlp.compare_exchange_weak(prev, localMax, std::memory_order_relaxed)) {\n            globalWorstX.store(localWorstX, std::memory_order_relaxed);\n            globalWorstY.store(localWorstY, std::memory_order_relaxed);\n            break;\n          }\n        }\n      });\n\n  return {\n      globalMaxUlp.load(),\n      globalWorstX.load(),\n      globalWorstY.load(),\n      globalCount3.load(),\n      globalValid.load()};\n}\n\n// --- Reporting ---\n\n// Evaluate all domains for a function and print a table.\ntemplate <typename BatchRunner, int32_t N>\nvoid evalFunc2D(\n    const char* name,\n    GroundTruth2D gt,\n    BatchRunner runner,\n    Domain2D (&domains)[N],\n    uint64_t numSamples) {\n  printf(\"%-28s  %5s  %10s  %12s  %-s\\n\", name, \"ULP\", \">=3ULP\", \"valid\", \"Worst (x, y)\");\n  for (int32_t i = 0; i < N; ++i) {\n    auto r = evalDomain2D(gt, runner, domains[i], numSamples);\n    printf(\n        \"  %-26s  %5u  %10llu  %12llu  (%.6g, %.6g)\\n\",\n        domains[i].label,\n        r.maxUlp,\n        static_cast<unsigned long long>(r.count3),\n        static_cast<unsigned long long>(r.validSamples),\n        r.worstX,\n        r.worstY);\n  }\n}\n\n// --- CLI helpers ---\n\nstruct EvalOptions {\n  uint64_t numSamples = 1000000000ULL; // 1B default\n  const char* filter = nullptr;\n};\n\ninline EvalOptions parseEvalOptions(int argc, char** argv) {\n  EvalOptions opts;\n  for (int i = 1; i < argc; ++i) {\n    if (strcmp(argv[i], \"--samples\") == 0 && i + 1 < argc) {\n      opts.numSamples = static_cast<uint64_t>(std::atof(argv[++i]));\n    } else if (strcmp(argv[i], \"--filter\") == 0 && i + 1 < argc) {\n      opts.filter = argv[++i];\n    } else if (strcmp(argv[i], \"--help\") == 0) {\n      printf(\"Usage: %s [--samples N] [--filter name]\\n\", argv[0]);\n      printf(\"  --samples N    Halton samples per domain (default: 1e9)\\n\");\n      printf(\"  --filter name  Only run variants containing 'name'\\n\");\n    }\n  }\n  return opts;\n}\n\ninline bool shouldRun(const EvalOptions& opts, const char* name) {\n  return opts.filter == nullptr || strstr(name, opts.filter) != nullptr;\n}\n\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "tests/fast_math/cbrt_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\n#include <iomanip>\n#include <limits>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto cbrt_acc = dispenso::fast_math::cbrt<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(Cbrt, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(cbrt_acc(0.0f), 0.0f) << std::setprecision(16) << cbrt_acc(0.0f);\n  EXPECT_EQ(cbrt_acc(-kInf), -kInf);\n  EXPECT_EQ(cbrt_acc(kInf), kInf);\n  EXPECT_NE(cbrt_acc(kNaN), cbrt_acc(kNaN));\n}\n\nconstexpr uint32_t kCbrtOuterUlps = 13; // 12 bits on Linux, MacOs, 13 with MSVC\n\nTEST(Cbrt, RangeNeg) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf,\n      dispenso::fast_math::cbrt<float>,\n      -std::numeric_limits<float>::max(),\n      -std::numeric_limits<float>::epsilon());\n\n  EXPECT_LE(result, kCbrtOuterUlps);\n}\nTEST(Cbrt, RangePos) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf,\n      dispenso::fast_math::cbrt<float>,\n      std::numeric_limits<float>::epsilon(),\n      std::numeric_limits<float>::max());\n\n  EXPECT_LE(result, kCbrtOuterUlps);\n}\nTEST(Cbrt, RangeSmall) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf,\n      dispenso::fast_math::cbrt<float>,\n      -std::numeric_limits<float>::epsilon(),\n      std::numeric_limits<float>::epsilon());\n\n  // cbrt handles denormals via rescaling — uniform ULP accuracy near zero.\n  EXPECT_LE(result, kCbrtOuterUlps);\n}\n\nconstexpr uint32_t kCbrtOuterUlpsAcc = 3;\n\nTEST(CbrtAccurate, RangeNeg) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf, cbrt_acc, -std::numeric_limits<float>::max(), -std::numeric_limits<float>::epsilon());\n\n  EXPECT_LE(result, kCbrtOuterUlpsAcc);\n}\nTEST(CbrtAccurate, RangePos) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf, cbrt_acc, std::numeric_limits<float>::epsilon(), std::numeric_limits<float>::max());\n\n  EXPECT_LE(result, kCbrtOuterUlpsAcc);\n}\nTEST(CbrtAccurate, RangeSmall) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      cbrtf,\n      cbrt_acc,\n      -std::numeric_limits<float>::epsilon(),\n      std::numeric_limits<float>::epsilon());\n\n  EXPECT_LE(result, kCbrtOuterUlpsAcc);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt cbrt_max(Flt x) {\n  return dfm::cbrt<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(\n    CbrtDefaultAll,\n    ::cbrtf,\n    dfm::cbrt,\n    -std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::max(),\n    kCbrtOuterUlps)\nFAST_MATH_ACCURACY_TESTS(\n    CbrtMaxAccAll,\n    ::cbrtf,\n    cbrt_max,\n    -std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::max(),\n    kCbrtOuterUlpsAcc)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles NaN/Inf.\nstatic const float kCbrtMaxAccSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    8.0f,\n    -8.0f,\n    27.0f,\n    -27.0f,\n    64.0f,\n    125.0f,\n    0.125f,\n    0.001f,\n    1e-20f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(\n    CbrtMaxAccSpecial,\n    ::cbrtf,\n    cbrt_max,\n    kCbrtMaxAccSpecials,\n    kCbrtOuterUlpsAcc)\n\n// Default traits don't handle NaN/Inf — only test in-domain values.\nstatic const float kCbrtDefaultSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    8.0f,\n    -8.0f,\n    27.0f,\n    -27.0f,\n    64.0f,\n    125.0f,\n    0.125f,\n    0.001f,\n    1000.0f,\n    -1000.0f};\nFAST_MATH_SPECIAL_TESTS(\n    CbrtDefaultSpecial,\n    ::cbrtf,\n    dfm::cbrt,\n    kCbrtDefaultSpecials,\n    kCbrtOuterUlps)\n"
  },
  {
    "path": "tests/fast_math/cos_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto cos_accurate = dispenso::fast_math::cos<float, dispenso::fast_math::MaxAccuracyTraits>;\n\n// MacOS seems to have a slightly busted cos and cosf, but cosl seems to agree with other platforms.\n#if defined(__APPLE__)\nfloat gt_cos(float x) {\n  return ::cosl(x);\n}\n#else\nauto gt_cos = ::cosf;\n#endif //__APPLE__\n\nTEST(Cos, SpecialValues) {\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n  auto cos = dispenso::fast_math::cos<float, dispenso::fast_math::MaxAccuracyTraits>;\n\n  EXPECT_NE(cos(-kInf), cos(-kInf));\n  EXPECT_NE(cos(kInf), cos(kInf));\n  EXPECT_NE(cos(kNaN), cos(kNaN));\n  EXPECT_EQ(cos(0.0f), 1.0f);\n}\n\nconstexpr uint32_t kCosAccurateUlps = 1;\nconstexpr uint32_t kCosAccurateUlpsLarge = 1;\nconstexpr uint32_t kCosAccurateUlpsVeryLarge = 2;\n\nconstexpr uint32_t kCosUlps = 1;\nconstexpr uint32_t kCosUlpsLarge = 1;\nconstexpr uint32_t kCosUlpsVeryLarge = 2;\n\nTEST(Cos, RangePi) {\n  auto result = dispenso::fast_math::evalAccuracy(gt_cos, cos_accurate, -kPi, kPi);\n\n  EXPECT_LE(result, kCosAccurateUlps);\n}\n\nTEST(Cos, Range128Pi) {\n  auto result = dispenso::fast_math::evalAccuracy(gt_cos, cos_accurate, -128 * kPi, 128 * kPi);\n\n  EXPECT_LE(result, kCosAccurateUlpsLarge);\n}\n\nTEST(Cos, Range1MPi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_cos, cos_accurate, -(1 << 20) * kPi, -128 * kPi);\n  EXPECT_LE(result, kCosAccurateUlpsVeryLarge);\n  result = dispenso::fast_math::evalAccuracy(gt_cos, cos_accurate, 128 * kPi, (1 << 20) * kPi);\n\n  EXPECT_LE(result, kCosAccurateUlpsVeryLarge);\n}\n\nTEST(CosLessAccurate, RangePi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_cos, dispenso::fast_math::cos<float>, -kPi, kPi);\n\n  EXPECT_LE(result, kCosUlps);\n}\n\nTEST(CosLessAccurate, Range128Pi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_cos, dispenso::fast_math::cos<float>, -128 * kPi, -kPi);\n\n  EXPECT_LE(result, kCosUlpsLarge);\n\n  result =\n      dispenso::fast_math::evalAccuracy(gt_cos, dispenso::fast_math::cos<float>, kPi, 128 * kPi);\n\n  EXPECT_LE(result, kCosUlpsLarge);\n}\n\nTEST(CosLessAccurate, Range32768Pi) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      gt_cos, dispenso::fast_math::cos<float>, -32768 * kPi, -128 * kPi);\n\n  EXPECT_LE(result, kCosUlpsVeryLarge);\n\n  result = dispenso::fast_math::evalAccuracy(\n      gt_cos, dispenso::fast_math::cos<float>, 128 * kPi, 32768 * kPi);\n\n  EXPECT_LE(result, kCosUlpsVeryLarge);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt cos_max(Flt x) {\n  return dfm::cos<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(\n    CosDefaultAll,\n    gt_cos,\n    dfm::cos,\n    -32768 * kPi,\n    32768 * kPi,\n    kCosUlpsVeryLarge)\nFAST_MATH_ACCURACY_TESTS(\n    CosMaxAccAll,\n    gt_cos,\n    cos_max,\n    -(1 << 20) * kPi,\n    (1 << 20) * kPi,\n    kCosAccurateUlpsVeryLarge)\n\n// Special values tested across all SIMD backends.\nstatic const float kCosSpecials[] = {\n    0.0f,\n    -0.0f,\n    kPi,\n    -kPi,\n    kPi_2,\n    -kPi_2,\n    2.0f * kPi,\n    -2.0f * kPi,\n    100.0f,\n    -100.0f,\n    1000.0f,\n    -1000.0f,\n    1e-6f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(CosMaxAccSpecial, gt_cos, cos_max, kCosSpecials, kCosAccurateUlpsVeryLarge)\nFAST_MATH_SPECIAL_TESTS(CosDefaultSpecial, gt_cos, dfm::cos, kCosSpecials, kCosUlpsVeryLarge)\n"
  },
  {
    "path": "tests/fast_math/erf_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nstatic float gt_erf(float x) {\n  return static_cast<float>(std::erf(static_cast<double>(x)));\n}\n\nconstexpr uint32_t kErfMaxUlps = 2;\n\nTEST(Erf, SpecialValues) {\n  EXPECT_EQ(dfm::erf(0.0f), 0.0f);\n  EXPECT_EQ(dfm::erf(-0.0f), -0.0f);\n  EXPECT_TRUE(std::signbit(dfm::erf(-0.0f)));\n  EXPECT_FLOAT_EQ(dfm::erf(1.0f), gt_erf(1.0f));\n  EXPECT_FLOAT_EQ(dfm::erf(-1.0f), gt_erf(-1.0f));\n  EXPECT_EQ(dfm::erf(std::numeric_limits<float>::infinity()), 1.0f);\n  EXPECT_EQ(dfm::erf(-std::numeric_limits<float>::infinity()), -1.0f);\n}\n\nTEST(Erf, NaN) {\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  EXPECT_TRUE(std::isnan(dfm::erf(nan)));\n}\n\nTEST(Erf, Saturation) {\n  // For |x| >= 3.92, erf rounds to ±1 in float.\n  EXPECT_EQ(dfm::erf(4.0f), 1.0f);\n  EXPECT_EQ(dfm::erf(-4.0f), -1.0f);\n  EXPECT_EQ(dfm::erf(10.0f), 1.0f);\n  EXPECT_EQ(dfm::erf(-10.0f), -1.0f);\n  EXPECT_EQ(dfm::erf(100.0f), 1.0f);\n  EXPECT_EQ(dfm::erf(-100.0f), -1.0f);\n}\n\nTEST(Erf, NearZero) {\n  // erf(x) ≈ (2/√π)·x for small x. Verify no cancellation.\n  float xs[] = {1e-7f, -1e-7f, 1e-5f, -1e-5f, 1e-3f, -1e-3f, 0.01f, -0.01f, 0.1f, -0.1f};\n  for (float x : xs) {\n    float expected = gt_erf(x);\n    float result = dfm::erf(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, kErfMaxUlps) << \"erf(\" << x << \"): expected=\" << expected << \" got=\" << result;\n  }\n}\n\n// Exhaustive accuracy tests — scalar + all available SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(Erf, gt_erf, dfm::erf, -4.0f, 4.0f, kErfMaxUlps)\n\n// Special values tested across all SIMD backends.\nstatic const float kErfSpecials[] = {\n    0.0f,\n    -0.0f,\n    0.5f,\n    -0.5f,\n    1.0f,\n    -1.0f,\n    2.0f,\n    -2.0f,\n    3.0f,\n    -3.0f,\n    4.0f,\n    -4.0f,\n    10.0f,\n    -10.0f,\n    100.0f,\n    -100.0f,\n    1e-7f,\n    -1e-7f,\n    0.01f,\n    -0.01f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(ErfSpecial, gt_erf, dfm::erf, kErfSpecials, kErfMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/eval.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nnamespace dispenso {\nnamespace fast_math {\nnamespace detail {\ndouble doNotOptimize = 0.0;\n} // namespace detail\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "tests/fast_math/eval.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <cmath>\n#include <cstdio>\n\n#include <dispenso/fast_math/util.h>\n\n// Float-precision math constants to avoid double-to-float conversion warnings.\nconstexpr float kPi = static_cast<float>(M_PI);\nconstexpr float kPi_2 = static_cast<float>(M_PI_2);\nconstexpr float kPi_4 = static_cast<float>(M_PI_4);\n\n// Reduce accuracy coverage for sanitizer and debug builds, which are much slower.\n// Clang uses __has_feature, GCC uses __SANITIZE_ADDRESS__/__SANITIZE_THREAD__.\n#if defined(__has_feature)\n#if __has_feature(address_sanitizer)\n#define REDUCE_TEST_CASES\n#elif __has_feature(thread_sanitizer)\n#define REDUCE_TEST_CASES\n#endif // relevant feature\n#endif // has_feature\n#if !defined(REDUCE_TEST_CASES)\n#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) || !defined(NDEBUG)\n#define REDUCE_TEST_CASES\n#endif\n#endif\n\nnamespace dispenso {\nnamespace fast_math {\n\nnamespace detail {\n\n#if !defined(REDUCE_TEST_CASES)\n// Use this to skip denormals\ninline float nextafter(float f) {\n  if (f == 0.0f) {\n    return std::numeric_limits<float>::min();\n  }\n\n  uint32_t u = bit_cast<uint32_t>(f);\n  if (u & 0x80000000) { // negative\n    if (u & 0x7f800000) {\n      --u;\n      if (u & 0x7f800000) {\n        return bit_cast<float>(u);\n      } else {\n        return 0.0f;\n      }\n    } else {\n      return 0.0f;\n    }\n  } else {\n    ++u;\n    return bit_cast<float>(u);\n  }\n}\n#else\n// Use this to skip denormals, also to skip many \"nexts\" at a time to speed up tests\ninline float nextafter(float f) {\n  if (f >= 0.0f && f < std::numeric_limits<float>::min()) {\n    return std::numeric_limits<float>::min();\n  }\n\n  uint32_t u = bit_cast<uint32_t>(f);\n  if (u & 0x80000000) { // negative\n    if (u & 0x7f800000) {\n      u -= 100;\n      if (u & 0x7f800000) {\n        return bit_cast<float>(u);\n      } else {\n        return 0.0f;\n      }\n    } else {\n      return 0.0f;\n    }\n  } else {\n    u += 100;\n    return bit_cast<float>(u);\n  }\n}\n#endif // REDUCE_TEST_CASES\n\n} // namespace detail\n\ntemplate <typename Func>\nvoid evalForEach(float rangeBegin, float rangeEnd, Func func) {\n  for (float f = rangeBegin; f <= rangeEnd; f = detail::nextafter(f)) {\n    func(f);\n  }\n}\n\ntemplate <typename GroundTruthFunc, typename ApproxFunc>\nuint32_t evalAccuracy(\n    GroundTruthFunc gtfunc,\n    ApproxFunc apxfunc,\n    float rangeBegin = -std::numeric_limits<float>::max(),\n    float rangeEnd = std::numeric_limits<float>::max()) {\n  uint32_t ulps = 0;\n  for (float f = rangeBegin; f <= rangeEnd; f = detail::nextafter(f)) {\n    float gt = gtfunc(f);\n    float a = apxfunc(f);\n    uint32_t lulps = float_distance(gt, a);\n    ulps = std::max(ulps, lulps);\n\n    if (lulps > 100) {\n      printf(\"%d, f(%.9g): %.9g, %.9g\\n\", lulps, f, gt, a);\n    }\n  }\n  return ulps;\n}\n\ntemplate <typename GroundTruthFunc, typename ApproxFunc>\nfloat evalAccuracyAbs(\n    GroundTruthFunc gtfunc,\n    ApproxFunc apxfunc,\n    float rangeBegin = -std::numeric_limits<float>::max(),\n    float rangeEnd = std::numeric_limits<float>::max()) {\n  float maxErr = 0.0f;\n  for (float f = rangeBegin; f <= rangeEnd; f = detail::nextafter(f)) {\n    float gt = gtfunc(f);\n    float a = apxfunc(f);\n    maxErr = std::max(maxErr, std::fabs(gt - a));\n  }\n  return maxErr;\n}\n\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "tests/fast_math/exp10_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nfloat groundTruth(float input) {\n  return ::powf(10.0f, input);\n}\n\nauto exp10_accurate = dispenso::fast_math::exp10<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(Exp10, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(exp10_accurate(0.0f), 1.0f);\n  EXPECT_EQ(exp10_accurate(-kInf), 0.0f);\n  EXPECT_EQ(exp10_accurate(kInf), kInf);\n  EXPECT_NE(exp10_accurate(kNaN), exp10_accurate(kNaN));\n}\n\nTEST(Exp10, Range) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(groundTruth, exp10_accurate, -40.0f, 40.0f);\n  EXPECT_LE(res, 2u);\n}\n\nTEST(Exp10LessAccurate, RangeMedium) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(\n      groundTruth, dispenso::fast_math::exp10<float>, -37.0f, 38.0f);\n  EXPECT_LE(res, 2u);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt exp10_max(Flt x) {\n  return dfm::exp10<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kExp10MaxUlps = 2;\nFAST_MATH_ACCURACY_TESTS(Exp10MaxAccAll, groundTruth, exp10_max, -40.0f, 40.0f, kExp10MaxUlps)\nFAST_MATH_ACCURACY_TESTS(Exp10DefaultAll, groundTruth, dfm::exp10, -37.0f, 38.0f, kExp10MaxUlps)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles NaN/Inf.\nstatic const float kExp10MaxAccSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    2.0f,\n    -2.0f,\n    38.0f,\n    -38.0f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(\n    Exp10MaxAccSpecial,\n    groundTruth,\n    exp10_max,\n    kExp10MaxAccSpecials,\n    kExp10MaxUlps)\n\n// Default traits only works for in-range floats.\nstatic const float kExp10DefaultSpecials[] =\n    {0.0f, -0.0f, 1.0f, -1.0f, 2.0f, -2.0f, 10.0f, -10.0f, 0.5f, -0.5f};\nFAST_MATH_SPECIAL_TESTS(\n    Exp10DefaultSpecial,\n    groundTruth,\n    dfm::exp10,\n    kExp10DefaultSpecials,\n    kExp10MaxUlps)\n"
  },
  {
    "path": "tests/fast_math/exp2_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Exp2, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  auto exp2 = dispenso::fast_math::exp2<float, dispenso::fast_math::MaxAccuracyTraits>;\n\n  EXPECT_EQ(exp2(0.0f), 1.0f);\n  EXPECT_EQ(exp2(-kInf), 0.0f);\n  EXPECT_EQ(exp2(kInf), kInf);\n  EXPECT_NE(exp2(kNaN), exp2(kNaN));\n}\n\n#ifdef _WIN32\nauto gtfunc = [](float f) { return static_cast<float>(::exp2l(f)); };\n#else\nauto gtfunc = ::exp2f;\n#endif //_WIN32\n\nTEST(Exp2, RangeSmall) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(gtfunc, dispenso::fast_math::exp2<float>, -127.0f, -1.0f);\n  EXPECT_LE(res, 1u);\n}\n\nTEST(Exp2, RangeMedium) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(gtfunc, dispenso::fast_math::exp2<float>, -1.0f, 0.0f);\n  EXPECT_LE(res, 1u);\n}\n\nTEST(Exp2, RangeLarge) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(gtfunc, dispenso::fast_math::exp2<float>, 0.0f, 128.0f);\n  EXPECT_LE(res, 1u);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kExp2MaxUlps = 1;\nFAST_MATH_ACCURACY_TESTS(Exp2All, gtfunc, dfm::exp2, -127.0f, 128.0f, kExp2MaxUlps)\n\n// Special values tested across all SIMD backends.\n// Default exp2 doesn't handle NaN/Inf — only test in-range values.\nstatic const float kExp2Specials[] =\n    {0.0f, -0.0f, 1.0f, -1.0f, 3.5f, -3.5f, 10.0f, -10.0f, 0.5f, 127.0f, -126.0f};\nFAST_MATH_SPECIAL_TESTS(Exp2Special, gtfunc, dfm::exp2, kExp2Specials, kExp2MaxUlps)\n"
  },
  {
    "path": "tests/fast_math/exp_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nstruct BoundsOnlyTraits {\n  static constexpr bool kMaxAccuracy = false;\n  static constexpr bool kBoundsValues = true;\n};\n\nauto exp_accurate = dispenso::fast_math::exp<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(Exp, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(exp_accurate(0.0f), 1.0f);\n  EXPECT_EQ(exp_accurate(-kInf), 0.0f);\n  EXPECT_EQ(exp_accurate(kInf), kInf);\n  EXPECT_NE(exp_accurate(kNaN), exp_accurate(kNaN));\n}\n\nTEST(Exp, RangeSmall) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::expf, exp_accurate, -127.0f, -40.0f);\n  EXPECT_LE(res, 1u);\n}\n\nTEST(Exp, RangeSmallish) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::expf, exp_accurate, -40.0f, 20.0f);\n  EXPECT_LE(res, 1u);\n}\nTEST(Exp, RangeMedium) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::expf, exp_accurate, 20.0f, 40.0f);\n  EXPECT_LE(res, 1u);\n}\n\nTEST(Exp, RangeLarge) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::expf, exp_accurate, 40.0f, 128.0f);\n  EXPECT_LE(res, 1u);\n}\n\nauto exp_bounds = dispenso::fast_math::exp<float, BoundsOnlyTraits>;\n\nTEST(ExpLessAccurateWBounds, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(exp_bounds(0.0f), 1.0f);\n  EXPECT_EQ(exp_bounds(-kInf), 0.0f);\n  EXPECT_EQ(exp_bounds(kInf), kInf);\n  EXPECT_NE(exp_bounds(kNaN), exp_bounds(kNaN));\n  EXPECT_LT(exp_bounds(-100.0f), 1e-38f);\n}\n\nTEST(ExpLessAccurateWBounds, Range_m100_100) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::expf, exp_bounds, -100.0f, 100.0f);\n  EXPECT_LE(res, 1u);\n}\n\nTEST(ExpLessAccurate, Range_m88_88) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(::expf, dispenso::fast_math::exp<float>, -88.0f, 88.0f);\n  EXPECT_LE(res, 3u);\n}\n\n// Wrappers for traits variants — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt exp_max_fn(Flt x) {\n  return dfm::exp<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\ntemplate <typename Flt>\nFlt exp_bounds_fn(Flt x) {\n  return dfm::exp<Flt, BoundsOnlyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kExpMaxAccMaxUlps = 1;\nconstexpr uint32_t kExpBoundsMaxUlps = 1;\nconstexpr uint32_t kExpDefaultMaxUlps = 3;\nFAST_MATH_ACCURACY_TESTS(ExpMaxAccAll, ::expf, exp_max_fn, -127.0f, 128.0f, kExpMaxAccMaxUlps)\nFAST_MATH_ACCURACY_TESTS(ExpBoundsAll, ::expf, exp_bounds_fn, -100.0f, 100.0f, kExpBoundsMaxUlps)\nFAST_MATH_ACCURACY_TESTS(ExpDefaultAll, ::expf, dfm::exp, -88.0f, 88.0f, kExpDefaultMaxUlps)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles NaN/Inf.\nstatic const float kExpMaxAccSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    5.0f,\n    -5.0f,\n    10.0f,\n    -10.0f,\n    88.7f,\n    -88.7f,\n    1e-10f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(ExpMaxAccSpecial, ::expf, exp_max_fn, kExpMaxAccSpecials, kExpMaxAccMaxUlps)\n\n// BoundsOnly handles NaN/Inf and clamps out-of-range inputs.\nstatic const float kExpBoundsSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    5.0f,\n    -5.0f,\n    89.0f,\n    -100.0f,\n    200.0f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(\n    ExpBoundsSpecial,\n    ::expf,\n    exp_bounds_fn,\n    kExpBoundsSpecials,\n    kExpBoundsMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/expm1_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nstatic float gt_expm1(float x) {\n  return static_cast<float>(std::expm1(static_cast<double>(x)));\n}\n\nTEST(Expm1, SpecialValues) {\n  EXPECT_EQ(dfm::expm1(0.0f), 0.0f);\n  EXPECT_FLOAT_EQ(dfm::expm1(1.0f), gt_expm1(1.0f));\n  EXPECT_FLOAT_EQ(dfm::expm1(-1.0f), gt_expm1(-1.0f));\n}\n\nTEST(Expm1, NearZero) {\n  // The primary use case: x very close to 0 where exp(x)-1 cancels.\n  float xs[] = {1e-7f, -1e-7f, 1e-5f, -1e-5f, 1e-3f, -1e-3f, 0.01f, -0.01f, 0.1f, -0.1f};\n  for (float x : xs) {\n    float expected = gt_expm1(x);\n    float result = dfm::expm1(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 2u) << \"expm1(\" << x << \"): expected=\" << expected << \" got=\" << result;\n  }\n}\n\nTEST(Expm1, RangeSmall) {\n  uint32_t ulps = dfm::evalAccuracy(gt_expm1, dfm::expm1<float>, -0.5f, 0.5f);\n  EXPECT_LE(ulps, 2u);\n}\n\nTEST(Expm1, RangeMedium) {\n  uint32_t ulps = dfm::evalAccuracy(gt_expm1, dfm::expm1<float>, -10.0f, 10.0f);\n  EXPECT_LE(ulps, 2u);\n}\n\nTEST(Expm1, RangeLarge) {\n  uint32_t ulps = dfm::evalAccuracy(gt_expm1, dfm::expm1<float>, -88.0f, 88.0f);\n  EXPECT_LE(ulps, 2u);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kExpm1MaxUlps = 2;\nFAST_MATH_ACCURACY_TESTS(Expm1All, gt_expm1, dfm::expm1, -88.0f, 88.0f, kExpm1MaxUlps)\n\n// Special values tested across all SIMD backends.\nstatic const float kExpm1Specials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    0.001f,\n    -0.001f,\n    1e-4f,\n    -1e-4f,\n    1e-7f,\n    -1e-7f,\n    5.0f,\n    -5.0f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(Expm1Special, gt_expm1, dfm::expm1, kExpm1Specials, kExpm1MaxUlps)\n"
  },
  {
    "path": "tests/fast_math/frexp_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Frexp, SpecialVals) {\n  int exp;\n  auto res = dispenso::fast_math::frexp(-std::numeric_limits<float>::infinity(), &exp);\n  EXPECT_EQ(res, -std::numeric_limits<float>::infinity());\n  res = dispenso::fast_math::frexp(std::numeric_limits<float>::infinity(), &exp);\n  EXPECT_EQ(res, std::numeric_limits<float>::infinity());\n\n  res = dispenso::fast_math::frexp(std::numeric_limits<float>::quiet_NaN(), &exp);\n  EXPECT_NE(res, res);\n}\n\n// evalForEach skips subnormals (nextafter jumps from 0 to float::min), which\n// is consistent with dispenso::frexp's intentional subnormal pass-through.\nTEST(Frexp, RangeNeg) {\n  dispenso::fast_math::evalForEach(-std::numeric_limits<float>::max(), 0.0f, [](float f) {\n    int exp;\n    int expT;\n    float a = ::frexpf(f, &exp);\n    float aT = dispenso::fast_math::frexp(f, &expT);\n    EXPECT_EQ(exp, expT) << \"frexpf(\" << f << \",&exp)\";\n    EXPECT_EQ(a, aT) << \"frexpf(\" << f << \",&exp)\";\n  });\n}\n\nTEST(Frexp, RangePos) {\n  dispenso::fast_math::evalForEach(0.0f, std::numeric_limits<float>::max(), [](float f) {\n    int exp;\n    int expT;\n    float a = ::frexpf(f, &exp);\n    float aT = dispenso::fast_math::frexp(f, &expT);\n    EXPECT_EQ(exp, expT) << \"frexpf(\" << f << \",&exp)\";\n    EXPECT_EQ(a, aT) << \"frexpf(\" << f << \",&exp)\";\n  });\n}\n\n// Unified SIMD frexp test — verify mantissa and exponent per lane.\n// Uses SimdTestTraits for float load/store, and stores int exponent via\n// aligned buffer + platform-specific store (frexp output is IntType_t<Flt>).\n//\n// Note: subnormals (denorm_min, etc.) are excluded. dispenso::frexp passes\n// subnormals through unchanged with exponent 0, rather than normalizing them\n// into [0.5, 1) as std::frexp does. This is intentional — the ldexp(frexp(x))\n// round-trip still works, but the mantissa contract is violated. See the frexp\n// docstring in fast_math.h for details.\nstatic const float kFrexpInputs[] = {\n    0.0f,\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    2.0f,\n    -2.0f,\n    100.0f,\n    0.001f,\n    1e-20f,\n    1e20f,\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::quiet_NaN()};\n\ntemplate <typename Flt>\nvoid checkFrexpSimd() {\n  using Traits = SimdTestTraits<Flt>;\n  using IntT = dfm::IntType_t<Flt>;\n  const int32_t N = Traits::laneCount();\n  constexpr int32_t numInputs =\n      static_cast<int32_t>(sizeof(kFrexpInputs) / sizeof(kFrexpInputs[0]));\n\n  alignas(64) float buf[kMaxSimdLanes];\n  alignas(64) float outMantissa[kMaxSimdLanes];\n\n  for (int32_t base = 0; base < numInputs; base += N) {\n    int32_t count = std::min(N, numInputs - base);\n    for (int32_t i = 0; i < count; ++i) {\n      buf[i] = kFrexpInputs[base + i];\n    }\n    for (int32_t i = count; i < N; ++i) {\n      buf[i] = buf[count - 1];\n    }\n\n    IntT exponent;\n    Flt result = dfm::frexp(Traits::load(buf), &exponent);\n    Traits::store(result, outMantissa);\n\n    // Extract int exponents by storing the result via bit_cast to float.\n    alignas(64) float expAsFloat[kMaxSimdLanes];\n    Traits::store(dfm::bit_cast<Flt>(exponent), expAsFloat);\n\n    for (int32_t i = 0; i < count; ++i) {\n      int scalarExp;\n      float scalarMantissa = ::frexpf(buf[i], &scalarExp);\n\n      if (std::isnan(buf[i])) {\n        EXPECT_TRUE(std::isnan(outMantissa[i])) << \"frexp(NaN) mantissa should be NaN\";\n      } else if (std::isinf(buf[i])) {\n        EXPECT_EQ(outMantissa[i], buf[i]) << \"frexp(inf) mantissa should be inf\";\n      } else {\n        EXPECT_EQ(outMantissa[i], scalarMantissa) << \"frexp(\" << buf[i] << \") mantissa mismatch\";\n        int32_t actualExp = dfm::bit_cast<int32_t>(expAsFloat[i]);\n        EXPECT_EQ(actualExp, scalarExp)\n            << \"frexp(\" << buf[i] << \") exponent mismatch: got \" << actualExp;\n      }\n    }\n  }\n}\n\n#if defined(__SSE4_1__)\nTEST(FrexpSse, SpecialVals) {\n  checkFrexpSimd<__m128>();\n}\n#endif\n#if defined(__AVX2__)\nTEST(FrexpAvx, SpecialVals) {\n  checkFrexpSimd<__m256>();\n}\n#endif\n#if defined(__AVX512F__)\nTEST(FrexpAvx512, SpecialVals) {\n  checkFrexpSimd<__m512>();\n}\n#endif\n#if defined(__aarch64__)\nTEST(FrexpNeon, SpecialVals) {\n  checkFrexpSimd<float32x4_t>();\n}\n#endif\n#if __has_include(\"hwy/highway.h\")\nTEST(FrexpHwy, SpecialVals) {\n  checkFrexpSimd<dfm::HwyFloat>();\n}\n#endif\n"
  },
  {
    "path": "tests/fast_math/hwy_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <cmath>\n#include <limits>\n\n#include <gtest/gtest.h>\n\n#if __has_include(\"hwy/highway.h\")\n#include \"hwy/highway.h\"\n\nnamespace dfm = dispenso::fast_math;\nnamespace hn = hwy::HWY_NAMESPACE;\nusing HwyFloat = dfm::HwyFloat;\nusing HwyInt32 = dfm::HwyInt32;\nusing HwyUint32 = dfm::HwyUint32;\nusing HwyFloatTag = dfm::HwyFloatTag;\nusing HwyInt32Tag = dfm::HwyInt32Tag;\nusing HwyUint32Tag = dfm::HwyUint32Tag;\n\n// Raw Highway vector type aliases — used in tests to exercise SimdTypeFor forwarding.\nusing HwyVecF = hn::Vec<HwyFloatTag>;\nusing HwyVecI = hn::Vec<HwyInt32Tag>;\nusing HwyVecU = hn::Vec<HwyUint32Tag>;\n\n// Lane count (constant per compile-time target).\nstatic size_t N() {\n  return hn::Lanes(HwyFloatTag{});\n}\n\nconstexpr size_t kMaxLanes = HWY_MAX_BYTES / sizeof(float);\n\n// Helpers: extract lane i from Highway vectors.\nstatic float lane(HwyVecF v, size_t i) {\n  HWY_ALIGN float buf[kMaxLanes];\n  hn::StoreU(v, HwyFloatTag{}, buf);\n  return buf[i];\n}\nstatic float lane(HwyFloat v, size_t i) {\n  return lane(v.v, i);\n}\n\nstatic int32_t lane(HwyVecI v, size_t i) {\n  HWY_ALIGN int32_t buf[kMaxLanes];\n  hn::StoreU(v, HwyInt32Tag{}, buf);\n  return buf[i];\n}\nstatic int32_t lane(HwyInt32 v, size_t i) {\n  return lane(v.v, i);\n}\n\nstatic uint32_t lane(HwyVecU v, size_t i) {\n  HWY_ALIGN uint32_t buf[kMaxLanes];\n  hn::StoreU(v, HwyUint32Tag{}, buf);\n  return buf[i];\n}\nstatic uint32_t lane(HwyUint32 v, size_t i) {\n  return lane(v.v, i);\n}\n\n// Helper: create HwyVecF from an array of values (must have N() entries).\nstatic HwyVecF loadF(const float* vals) {\n  return hn::LoadU(HwyFloatTag{}, vals);\n}\n\n// Helper: create HwyVecI from an array of values.\nstatic HwyVecI loadI(const int32_t* vals) {\n  return hn::LoadU(HwyInt32Tag{}, vals);\n}\n\n// ---- HwyFloat basic arithmetic ----\n\nTEST(HwyFloat, Broadcast) {\n  HwyFloat v(3.0f);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(v, i), 3.0f);\n  }\n}\n\nTEST(HwyFloat, Arithmetic) {\n  // Use sequential values: 1, 2, 3, ...\n  HWY_ALIGN float a_vals[kMaxLanes];\n  HWY_ALIGN float b_vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    a_vals[i] = static_cast<float>(i + 1);\n    b_vals[i] = static_cast<float>(i + 5);\n  }\n  HwyFloat a = loadF(a_vals);\n  HwyFloat b = loadF(b_vals);\n\n  HwyFloat sum = a + b;\n  HwyFloat diff = a - b;\n  HwyFloat prod = a * b;\n  HwyFloat quot = a / b;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(sum, i), a_vals[i] + b_vals[i]);\n    EXPECT_EQ(lane(diff, i), a_vals[i] - b_vals[i]);\n    EXPECT_EQ(lane(prod, i), a_vals[i] * b_vals[i]);\n    EXPECT_NEAR(lane(quot, i), a_vals[i] / b_vals[i], 1e-6f);\n  }\n}\n\nTEST(HwyFloat, Negation) {\n  HWY_ALIGN float vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = static_cast<float>(i + 1);\n  }\n  HwyFloat v = loadF(vals);\n  HwyFloat neg = -v;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(neg, i), -vals[i]);\n  }\n\n  // Test -0.0f: negation should flip the sign bit.\n  HwyFloat z(0.0f);\n  HwyFloat negz = -z;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_TRUE(std::signbit(lane(negz, i)));\n  }\n}\n\nTEST(HwyFloat, CompoundAssignment) {\n  HwyFloat a(2.0f);\n  HwyFloat b(3.0f);\n\n  HwyFloat c = a;\n  c += b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(c, i), 5.0f);\n  }\n\n  c = a;\n  c -= b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(c, i), -1.0f);\n  }\n\n  c = a;\n  c *= b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(c, i), 6.0f);\n  }\n}\n\n// ---- HwyFloat comparisons ----\n\nTEST(HwyFloat, Comparisons) {\n  HwyFloat a(1.0f);\n  HwyFloat b(2.0f);\n\n  // a < b: all lanes should be true (all-ones mask).\n  HwyFloat lt = a < b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, i)), 0u) << \"Lane \" << i;\n  }\n\n  // a > b: all lanes should be false.\n  HwyFloat gt = a > b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(gt, i)), 0u) << \"Lane \" << i;\n  }\n\n  // a == a: all lanes should be true.\n  HwyFloat eq = a == a;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(eq, i)), 0xFFFFFFFFu) << \"Lane \" << i;\n  }\n\n  // a != b: all lanes should be true.\n  HwyFloat ne = a != b;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_NE(dfm::bit_cast<uint32_t>(lane(ne, i)), 0u) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyFloat, LogicalNot) {\n  HwyFloat a(1.0f);\n  HwyFloat b(2.0f);\n  HwyFloat mask = a < b; // all true\n  HwyFloat notmask = !mask;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(notmask, i)), 0u) << \"Lane \" << i;\n  }\n}\n\n// ---- HwyInt32 ----\n\nTEST(HwyInt32, ArithmeticAndShifts) {\n  HWY_ALIGN int32_t a_vals[kMaxLanes];\n  HWY_ALIGN int32_t b_vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    a_vals[i] = static_cast<int32_t>(10 + i);\n    b_vals[i] = static_cast<int32_t>(3 + i);\n  }\n  HwyInt32 a = loadI(a_vals);\n  HwyInt32 b = loadI(b_vals);\n\n  HwyInt32 sum = a + b;\n  HwyInt32 diff = a - b;\n  HwyInt32 prod = a * b;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(sum, i), a_vals[i] + b_vals[i]);\n    EXPECT_EQ(lane(diff, i), a_vals[i] - b_vals[i]);\n    EXPECT_EQ(lane(prod, i), a_vals[i] * b_vals[i]);\n  }\n\n  // Shifts.\n  HwyInt32 shl = a << 2;\n  HwyInt32 shr = a >> 1;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(shl, i), a_vals[i] << 2);\n    EXPECT_EQ(lane(shr, i), a_vals[i] >> 1);\n  }\n}\n\nTEST(HwyInt32, Negation) {\n  HwyInt32 a(42);\n  HwyInt32 neg = -a;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(neg, i), -42);\n  }\n}\n\nTEST(HwyInt32, Bitwise) {\n  HwyInt32 a(0xFF00FF00);\n  HwyInt32 b(0x0F0F0F0F);\n\n  HwyInt32 andResult = a & b;\n  HwyInt32 orResult = a | b;\n  HwyInt32 xorResult = a ^ b;\n  HwyInt32 notResult = ~a;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(andResult, i), int32_t(0xFF00FF00 & 0x0F0F0F0F));\n    EXPECT_EQ(lane(orResult, i), int32_t(0xFF00FF00 | 0x0F0F0F0F));\n    EXPECT_EQ(lane(xorResult, i), int32_t(0xFF00FF00 ^ 0x0F0F0F0F));\n    EXPECT_EQ(lane(notResult, i), ~int32_t(0xFF00FF00));\n  }\n}\n\nTEST(HwyInt32, Comparisons) {\n  HwyInt32 a(5);\n  HwyInt32 b(10);\n\n  HwyInt32 lt = a < b;\n  HwyInt32 gt = a > b;\n  HwyInt32 eq = a == a;\n  HwyInt32 ne = a != b;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(lt, i), -1); // all-ones\n    EXPECT_EQ(lane(gt, i), 0);\n    EXPECT_EQ(lane(eq, i), -1);\n    EXPECT_EQ(lane(ne, i), -1);\n  }\n}\n\n// ---- HwyUint32 ----\n\nTEST(HwyUint32, ArithmeticAndShifts) {\n  HwyUint32 a(100u);\n  HwyUint32 b(30u);\n\n  HwyUint32 sum = a + b;\n  HwyUint32 diff = a - b;\n  HwyUint32 prod = a * b;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(sum, i), 130u);\n    EXPECT_EQ(lane(diff, i), 70u);\n    EXPECT_EQ(lane(prod, i), 3000u);\n  }\n\n  // Logical right shift.\n  HwyUint32 shr = a >> 2;\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(shr, i), 25u);\n  }\n}\n\nTEST(HwyUint32, UnsignedComparisons) {\n  HwyUint32 a(0x80000001u); // large unsigned value\n  HwyUint32 b(1u);\n\n  HwyUint32 gt = a > b;\n  HwyUint32 lt = a < b;\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(gt, i), 0xFFFFFFFFu) << \"Lane \" << i; // a > b unsigned\n    EXPECT_EQ(lane(lt, i), 0u) << \"Lane \" << i;\n  }\n}\n\n// ---- bit_cast ----\n\nTEST(HwyBitCast, FloatIntRoundTrip) {\n  HwyFloat f(1.0f);\n  HwyInt32 i = dfm::bit_cast<HwyInt32>(f);\n  HwyFloat f2 = dfm::bit_cast<HwyFloat>(i);\n\n  for (size_t j = 0; j < N(); ++j) {\n    EXPECT_EQ(lane(f2, j), 1.0f);\n    EXPECT_EQ(lane(i, j), 0x3f800000);\n  }\n}\n\nTEST(HwyBitCast, FloatUintRoundTrip) {\n  HwyFloat f(-1.0f);\n  HwyUint32 u = dfm::bit_cast<HwyUint32>(f);\n  HwyFloat f2 = dfm::bit_cast<HwyFloat>(u);\n\n  for (size_t j = 0; j < N(); ++j) {\n    EXPECT_EQ(lane(f2, j), -1.0f);\n    EXPECT_EQ(lane(u, j), 0xBF800000u);\n  }\n}\n\n// ---- FloatTraits ----\n\nTEST(HwyFloatTraits, Conditional) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  // Create a mask: alternating true/false per lane.\n  HWY_ALIGN float vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = (i % 2 == 0) ? 1.0f : 2.0f;\n  }\n  HwyVecF input = loadF(vals);\n  HwyFloat mask = input < HwyFloat(1.5f); // even lanes true, odd lanes false\n\n  HwyFloat x(10.0f);\n  HwyFloat y(20.0f);\n  HwyFloat result = FT::conditional(mask, x, y);\n\n  for (size_t i = 0; i < N(); ++i) {\n    float expected = (i % 2 == 0) ? 10.0f : 20.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyFloatTraits, ConditionalInt32) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  HWY_ALIGN float vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = (i % 2 == 0) ? 1.0f : 2.0f;\n  }\n  HwyFloat mask = loadF(vals) < HwyFloat(1.5f);\n\n  HwyInt32 x(100);\n  HwyInt32 y(200);\n  HwyInt32 result = FT::conditional(mask, x, y);\n\n  for (size_t i = 0; i < N(); ++i) {\n    int32_t expected = (i % 2 == 0) ? 100 : 200;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyFloatTraits, ConditionalWithLaneWideMask) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  // Create an integer lane-wide mask (alternating -1/0).\n  HWY_ALIGN int32_t mask_vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    mask_vals[i] = (i % 2 == 0) ? -1 : 0;\n  }\n  HwyInt32 mask = loadI(mask_vals);\n\n  HwyFloat x(10.0f);\n  HwyFloat y(20.0f);\n  HwyFloat result = FT::conditional(mask, x, y);\n\n  for (size_t i = 0; i < N(); ++i) {\n    float expected = (i % 2 == 0) ? 10.0f : 20.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyFloatTraits, Apply) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  HwyFloat mask = HwyFloat(1.0f) < HwyFloat(2.0f); // all true\n  HwyFloat x(42.0f);\n  HwyFloat result = FT::apply(mask, x);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), 42.0f) << \"Lane \" << i;\n  }\n\n  // All false mask.\n  HwyFloat falseMask = HwyFloat(2.0f) < HwyFloat(1.0f);\n  HwyFloat result2 = FT::apply(falseMask, x);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result2, i), 0.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyFloatTraits, FmaAndSqrt) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  HwyFloat a(2.0f);\n  HwyFloat b(3.0f);\n  HwyFloat c(4.0f);\n\n  // fma: a*b + c = 2*3 + 4 = 10\n  HwyFloat fma_result = FT::fma(a, b, c);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_NEAR(lane(fma_result, i), 10.0f, 1e-6f);\n  }\n\n  // sqrt(4.0) = 2.0\n  HwyFloat sq = FT::sqrt(c);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(sq, i), 2.0f);\n  }\n}\n\nTEST(HwyFloatTraits, MinMax) {\n  using FT = dfm::FloatTraits<HwyFloat>;\n\n  HWY_ALIGN float a_vals[kMaxLanes];\n  HWY_ALIGN float b_vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    a_vals[i] = static_cast<float>(i);\n    b_vals[i] = static_cast<float>(N() - 1 - i);\n  }\n  HwyFloat a = loadF(a_vals);\n  HwyFloat b = loadF(b_vals);\n\n  HwyFloat mn = FT::min(a, b);\n  HwyFloat mx = FT::max(a, b);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(mn, i), std::min(a_vals[i], b_vals[i])) << \"Lane \" << i;\n    EXPECT_EQ(lane(mx, i), std::max(a_vals[i], b_vals[i])) << \"Lane \" << i;\n  }\n}\n\n// ---- Util functions ----\n\nTEST(HwyUtil, FloorSmall) {\n  HWY_ALIGN float vals[kMaxLanes];\n  float test_vals[] = {1.7f, -1.7f, 2.0f, -0.5f, 3.3f, -3.3f, 0.0f, 100.9f};\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = test_vals[i % 8];\n  }\n  HwyVecF input = loadF(vals);\n  HwyFloat result = dfm::floor_small(input);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), std::floor(vals[i])) << \"Lane \" << i << \" input=\" << vals[i];\n  }\n}\n\nTEST(HwyUtil, ConvertToInt) {\n  HWY_ALIGN float vals[kMaxLanes];\n  float test_vals[] = {1.5f, -1.5f, 2.5f, -2.5f, 3.5f, -3.5f, 0.4f, 100.6f};\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = test_vals[i % 8];\n  }\n  HwyVecF input = loadF(vals);\n  HwyInt32 result = dfm::convert_to_int(input);\n\n  for (size_t i = 0; i < N(); ++i) {\n    int32_t expected = static_cast<int32_t>(std::nearbyint(vals[i]));\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i << \" input=\" << vals[i];\n  }\n}\n\nTEST(HwyUtil, ConvertToIntNaN) {\n  HwyFloat nan_val(std::numeric_limits<float>::quiet_NaN());\n  HwyInt32 result = dfm::convert_to_int(nan_val);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), 0) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, Gather) {\n  float table[16];\n  for (int j = 0; j < 16; ++j) {\n    table[j] = static_cast<float>(j * 10);\n  }\n\n  HWY_ALIGN int32_t idx[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    idx[i] = static_cast<int32_t>(i % 16);\n  }\n  HwyInt32 index = loadI(idx);\n  HwyFloat result = dfm::gather<HwyFloat>(table, index);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), table[idx[i]]) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, IntDivBy3) {\n  HWY_ALIGN int32_t vals[kMaxLanes];\n  int32_t test_vals[] = {3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48};\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = test_vals[i % 16];\n  }\n  HwyInt32 input = loadI(vals);\n  HwyInt32 result = dfm::int_div_by_3(input);\n\n  for (size_t i = 0; i < N(); ++i) {\n    int32_t expected = dfm::int_div_by_3(vals[i]);\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i << \" input=\" << vals[i];\n  }\n}\n\nTEST(HwyUtil, Signof) {\n  HWY_ALIGN float vals[kMaxLanes];\n  float test_vals[] = {1.0f, -1.0f, 100.0f, -0.5f, 0.0f, -0.0f, 42.0f, -42.0f};\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = test_vals[i % 8];\n  }\n  HwyVecF input = loadF(vals);\n  HwyFloat result = dfm::signof(input);\n\n  for (size_t i = 0; i < N(); ++i) {\n    float expected = std::signbit(vals[i]) ? -1.0f : 1.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i << \" input=\" << vals[i];\n  }\n}\n\nTEST(HwyUtil, Signofi) {\n  HWY_ALIGN int32_t vals[kMaxLanes];\n  int32_t test_vals[] = {1, -1, 0, -100, 50, -50, 0, 1000};\n  for (size_t i = 0; i < N(); ++i) {\n    vals[i] = test_vals[i % 8];\n  }\n  HwyInt32 input = loadI(vals);\n  HwyInt32 result = dfm::signofi(input);\n\n  for (size_t i = 0; i < N(); ++i) {\n    int32_t expected = (vals[i] < 0) ? -1 : 1;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i << \" input=\" << vals[i];\n  }\n}\n\nTEST(HwyUtil, Nonnormal) {\n  HwyFloat inf_val(std::numeric_limits<float>::infinity());\n  HwyFloat nan_val(std::numeric_limits<float>::quiet_NaN());\n  HwyFloat normal_val(1.0f);\n\n  HwyInt32 inf_nn = dfm::nonnormal(inf_val);\n  HwyInt32 nan_nn = dfm::nonnormal(nan_val);\n  HwyInt32 normal_nn = dfm::nonnormal(normal_val);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(inf_nn, i), -1) << \"Inf should be nonnormal\";\n    EXPECT_EQ(lane(nan_nn, i), -1) << \"NaN should be nonnormal\";\n    EXPECT_EQ(lane(normal_nn, i), 0) << \"1.0 should not be nonnormal\";\n  }\n}\n\nTEST(HwyUtil, BoolAsOne) {\n  HwyFloat true_mask = HwyFloat(1.0f) < HwyFloat(2.0f); // all true\n  HwyFloat false_mask = HwyFloat(2.0f) < HwyFloat(1.0f); // all false\n\n  HwyFloat true_one = dfm::bool_as_one<HwyFloat, HwyFloat>(true_mask);\n  HwyFloat false_one = dfm::bool_as_one<HwyFloat, HwyFloat>(false_mask);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(true_one, i), 1.0f) << \"Lane \" << i;\n    EXPECT_EQ(lane(false_one, i), 0.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, NBoolAsOne) {\n  HwyFloat true_mask = HwyFloat(1.0f) < HwyFloat(2.0f);\n  HwyFloat false_mask = HwyFloat(2.0f) < HwyFloat(1.0f);\n\n  HwyFloat true_nbo = dfm::nbool_as_one<HwyFloat, HwyFloat>(true_mask);\n  HwyFloat false_nbo = dfm::nbool_as_one<HwyFloat, HwyFloat>(false_mask);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(true_nbo, i), 0.0f) << \"Lane \" << i;\n    EXPECT_EQ(lane(false_nbo, i), 1.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, BoolAsMask) {\n  HwyFloat true_mask = HwyFloat(1.0f) < HwyFloat(2.0f);\n  HwyInt32 int_mask = dfm::bool_as_mask<HwyInt32, HwyFloat>(true_mask);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(int_mask, i), -1) << \"Lane \" << i; // all-ones = -1\n  }\n}\n\nTEST(HwyUtil, BoolApplyOrZero) {\n  HWY_ALIGN float mask_vals[kMaxLanes];\n  for (size_t i = 0; i < N(); ++i) {\n    mask_vals[i] = (i % 2 == 0) ? 1.0f : 2.0f;\n  }\n  HwyFloat input = loadF(mask_vals);\n  HwyFloat mask = input < HwyFloat(1.5f); // even lanes true\n\n  HwyFloat value(42.0f);\n  HwyFloat result = dfm::bool_apply_or_zero(mask, value);\n\n  for (size_t i = 0; i < N(); ++i) {\n    float expected = (i % 2 == 0) ? 42.0f : 0.0f;\n    EXPECT_EQ(lane(result, i), expected) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, ClampAllowNan) {\n  HwyFloat x(3.0f);\n  HwyFloat mn(1.0f);\n  HwyFloat mx(2.0f);\n  HwyFloat result = dfm::clamp_allow_nan(x, mn, mx);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), 2.0f) << \"Lane \" << i;\n  }\n\n  // NaN should propagate.\n  HwyFloat nan_val(std::numeric_limits<float>::quiet_NaN());\n  HwyFloat nan_result = dfm::clamp_allow_nan(nan_val, mn, mx);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_TRUE(std::isnan(lane(nan_result, i))) << \"Lane \" << i;\n  }\n}\n\nTEST(HwyUtil, ClampNoNan) {\n  HwyFloat x(0.5f);\n  HwyFloat mn(1.0f);\n  HwyFloat mx(2.0f);\n  HwyFloat result = dfm::clamp_no_nan(x, mn, mx);\n\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_EQ(lane(result, i), 1.0f) << \"Lane \" << i;\n  }\n\n  // NaN should be suppressed.\n  HwyFloat nan_val(std::numeric_limits<float>::quiet_NaN());\n  HwyFloat nan_result = dfm::clamp_no_nan(nan_val, mn, mx);\n  for (size_t i = 0; i < N(); ++i) {\n    EXPECT_FALSE(std::isnan(lane(nan_result, i))) << \"Lane \" << i;\n    EXPECT_GE(lane(nan_result, i), 1.0f);\n    EXPECT_LE(lane(nan_result, i), 2.0f);\n  }\n}\n\n#else // !__has_include(\"hwy/highway.h\")\n\n// Dummy test so the binary does something when Highway is not available.\nTEST(HwyFloat, Unavailable) {\n  GTEST_SKIP() << \"Highway not available\";\n}\n\n#endif // __has_include(\"hwy/highway.h\")\n"
  },
  {
    "path": "tests/fast_math/hypot_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <cmath>\n#include <limits>\n#include <random>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\n// Ground truth: double-precision sqrt(x*x + y*y) cast to float.\nstatic float hypotRef(float x, float y) {\n  double xd = static_cast<double>(x);\n  double yd = static_cast<double>(y);\n  return static_cast<float>(std::sqrt(std::fma(xd, xd, yd * yd)));\n}\n\nTEST(Hypot, SpecialValues) {\n  EXPECT_EQ(dfm::hypot(0.0f, 0.0f), 0.0f);\n  EXPECT_EQ(dfm::hypot(3.0f, 0.0f), 3.0f);\n  EXPECT_EQ(dfm::hypot(0.0f, 4.0f), 4.0f);\n  EXPECT_EQ(dfm::hypot(-3.0f, 0.0f), 3.0f);\n  EXPECT_EQ(dfm::hypot(0.0f, -4.0f), 4.0f);\n  EXPECT_FLOAT_EQ(dfm::hypot(3.0f, 4.0f), 5.0f);\n  EXPECT_FLOAT_EQ(dfm::hypot(1.0f, 1.0f), std::sqrt(2.0f));\n}\n\nTEST(Hypot, GridNearZero) {\n  constexpr int32_t kMax = 2048;\n\n  float quantizer = 0.5f;\n  quantizer *= quantizer;\n  quantizer *= quantizer;\n  quantizer *= quantizer;\n  quantizer *= 0.25f;\n\n  uint32_t maxUlps = 0;\n  for (int32_t yi = -kMax; yi <= kMax; ++yi) {\n    for (int32_t xi = -kMax; xi <= kMax; ++xi) {\n      float x = static_cast<float>(xi) * quantizer;\n      float y = static_cast<float>(yi) * quantizer;\n      maxUlps = std::max(maxUlps, dfm::float_distance(hypotRef(x, y), dfm::hypot(x, y)));\n    }\n  }\n  EXPECT_LE(maxUlps, 1u);\n}\n\nTEST(Hypot, RandomNormal) {\n  constexpr size_t kNumSamples = 1 << 24;\n  std::mt19937 gen(42);\n  std::uniform_real_distribution<float> dis(-1e5f, 1e5f);\n\n  uint32_t maxUlps = 0;\n  for (size_t i = 0; i < kNumSamples; ++i) {\n    float x = dis(gen);\n    float y = dis(gen);\n    maxUlps = std::max(maxUlps, dfm::float_distance(hypotRef(x, y), dfm::hypot(x, y)));\n  }\n  EXPECT_LE(maxUlps, 1u);\n}\n\nTEST(Hypot, RandomWide) {\n  constexpr size_t kNumSamples = 1 << 24;\n  std::mt19937 gen(77);\n  std::uniform_real_distribution<float> dis(-1e30f, 1e30f);\n\n  uint32_t maxUlps = 0;\n  for (size_t i = 0; i < kNumSamples; ++i) {\n    float x = dis(gen);\n    float y = dis(gen);\n    maxUlps = std::max(maxUlps, dfm::float_distance(hypotRef(x, y), dfm::hypot(x, y)));\n  }\n  EXPECT_LE(maxUlps, 1u);\n}\n\nTEST(Hypot, RandomTiny) {\n  constexpr size_t kNumSamples = 1 << 24;\n  std::mt19937 gen(99);\n  std::uniform_real_distribution<float> dis(-1e-30f, 1e-30f);\n\n  uint32_t maxUlps = 0;\n  for (size_t i = 0; i < kNumSamples; ++i) {\n    float x = dis(gen);\n    float y = dis(gen);\n    maxUlps = std::max(maxUlps, dfm::float_distance(hypotRef(x, y), dfm::hypot(x, y)));\n  }\n  EXPECT_LE(maxUlps, 1u);\n}\n\nTEST(Hypot, Symmetry) {\n  std::mt19937 gen(123);\n  std::uniform_real_distribution<float> dis(-1e10f, 1e10f);\n\n  for (size_t i = 0; i < 100000; ++i) {\n    float x = dis(gen);\n    float y = dis(gen);\n    EXPECT_EQ(dfm::hypot(x, y), dfm::hypot(y, x));\n    EXPECT_EQ(dfm::hypot(x, y), dfm::hypot(-x, y));\n    EXPECT_EQ(dfm::hypot(x, y), dfm::hypot(x, -y));\n    EXPECT_EQ(dfm::hypot(x, y), dfm::hypot(-x, -y));\n  }\n}\n\nTEST(Hypot, DiagonalSweep) {\n  uint32_t maxUlps = 0;\n  for (float x = 1e-20f; x < 1e20f; x *= 1.5f) {\n    maxUlps = std::max(maxUlps, dfm::float_distance(hypotRef(x, x), dfm::hypot(x, x)));\n  }\n  EXPECT_LE(maxUlps, 1u);\n}\n\n// --- hypot with MaxAccuracyTraits (IEEE boundary conditions) ---\n\ntemplate <typename... Args>\nstatic float hypotBounds(Args... args) {\n  return dfm::hypot<float, dfm::MaxAccuracyTraits>(args...);\n}\n\nTEST(HypotBounds, InfFinite) {\n  float inf = std::numeric_limits<float>::infinity();\n  // hypot(±inf, finite) = +inf\n  EXPECT_EQ(hypotBounds(inf, 3.0f), inf);\n  EXPECT_EQ(hypotBounds(-inf, 3.0f), inf);\n  EXPECT_EQ(hypotBounds(3.0f, inf), inf);\n  EXPECT_EQ(hypotBounds(3.0f, -inf), inf);\n  EXPECT_EQ(hypotBounds(inf, 0.0f), inf);\n  EXPECT_EQ(hypotBounds(0.0f, -inf), inf);\n}\n\nTEST(HypotBounds, InfNaN) {\n  float inf = std::numeric_limits<float>::infinity();\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  // IEEE 754: hypot(±inf, NaN) = +inf (inf wins over NaN)\n  float r1 = hypotBounds(inf, nan);\n  float r2 = hypotBounds(-inf, nan);\n  float r3 = hypotBounds(nan, inf);\n  float r4 = hypotBounds(nan, -inf);\n  EXPECT_TRUE(std::isinf(r1) && r1 > 0) << \"hypot(inf, nan) = \" << r1;\n  EXPECT_TRUE(std::isinf(r2) && r2 > 0) << \"hypot(-inf, nan) = \" << r2;\n  EXPECT_TRUE(std::isinf(r3) && r3 > 0) << \"hypot(nan, inf) = \" << r3;\n  EXPECT_TRUE(std::isinf(r4) && r4 > 0) << \"hypot(nan, -inf) = \" << r4;\n}\n\nTEST(HypotBounds, NaNFinite) {\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  // hypot(NaN, finite) = NaN (when neither is inf)\n  EXPECT_TRUE(std::isnan(hypotBounds(nan, 3.0f)));\n  EXPECT_TRUE(std::isnan(hypotBounds(3.0f, nan)));\n  EXPECT_TRUE(std::isnan(hypotBounds(nan, nan)));\n}\n\n// Wrappers for traits variants — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt hypot_max(Flt x, Flt y) {\n  return dfm::hypot<Flt, dfm::MaxAccuracyTraits>(x, y);\n}\n\n// Default hypot — positive domain, no NaN/Inf handling needed.\nconstexpr uint32_t kHypotUlps = 1;\n// clang-format off\nstatic const float kHypotDefaultX[] = {\n    3.0f, 0.0f, 0.0f, -3.0f, 0.0f, 1.0f,\n    1e-20f, 1e10f, 1e-30f, 100.0f, 0.001f};\nstatic const float kHypotDefaultY[] = {\n    4.0f, 4.0f, 0.0f, 0.0f, -4.0f, 1.0f,\n    1e-20f, 1e10f, 1e-30f, 200.0f, 0.002f};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    HypotDefaultSpecial,\n    hypotRef,\n    dfm::hypot,\n    kHypotDefaultX,\n    kHypotDefaultY,\n    kHypotUlps)\n\n// MaxAccuracy handles NaN/Inf (IEEE: hypot(±inf, NaN) = +inf).\n// clang-format off\nstatic const float kHypotMaxAccX[] = {\n    3.0f, 0.0f, 0.0f, -3.0f, 1.0f,\n    1e-20f, 1e10f, 100.0f,\n    std::numeric_limits<float>::infinity(),                              // inf wins over anything\n    -std::numeric_limits<float>::infinity(),\n    3.0f,                                                               // finite + inf\n    std::numeric_limits<float>::infinity(),                              // inf + NaN → inf\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::quiet_NaN(),                            // NaN + finite → NaN\n    3.0f,\n    std::numeric_limits<float>::quiet_NaN()};\nstatic const float kHypotMaxAccY[] = {\n    4.0f, 4.0f, 0.0f, 0.0f, 1.0f,\n    1e-20f, 1e10f, 200.0f,\n    3.0f,\n    3.0f,\n    std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::quiet_NaN(),\n    3.0f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::quiet_NaN()};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    HypotMaxAccSpecial,\n    ::hypotf,\n    hypot_max,\n    kHypotMaxAccX,\n    kHypotMaxAccY,\n    kHypotUlps)\n"
  },
  {
    "path": "tests/fast_math/ldexp_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Ldexp, SpecialVals) {\n  auto res = dispenso::fast_math::ldexp(-std::numeric_limits<float>::infinity(), 1);\n  EXPECT_EQ(res, -std::numeric_limits<float>::infinity());\n  res = dispenso::fast_math::ldexp(std::numeric_limits<float>::infinity(), 2);\n  EXPECT_EQ(res, std::numeric_limits<float>::infinity());\n\n  res = dispenso::fast_math::ldexp(std::numeric_limits<float>::quiet_NaN(), 7);\n  EXPECT_NE(res, res);\n\n  int exp;\n  float tval = -0.49999997f;\n\n  float a = dispenso::fast_math::frexp(tval, &exp);\n  res = dispenso::fast_math::ldexp(a, exp);\n  EXPECT_EQ(res, tval);\n}\n\nTEST(Ldexp, Range) {\n  auto test = [](float f) {\n    int exp;\n    float a = dispenso::fast_math::frexp(f, &exp);\n    float res = dispenso::fast_math::ldexp(a, exp);\n    EXPECT_EQ(res, f);\n  };\n\n  dispenso::fast_math::evalForEach(\n      -std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), test);\n}\n\n// Unified SIMD ldexp test — round-trip frexp → ldexp, verified per lane.\nstatic const float kLdexpInputs[] = {\n    1.0f,\n    -1.0f,\n    0.5f,\n    -0.5f,\n    2.0f,\n    -2.0f,\n    100.0f,\n    -100.0f,\n    0.001f,\n    1e-20f,\n    1e20f,\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::quiet_NaN()};\n\ntemplate <typename Flt>\nvoid checkLdexpSimd() {\n  using Traits = SimdTestTraits<Flt>;\n  using IntT = dfm::IntType_t<Flt>;\n  const int32_t N = Traits::laneCount();\n  constexpr int32_t numInputs =\n      static_cast<int32_t>(sizeof(kLdexpInputs) / sizeof(kLdexpInputs[0]));\n\n  alignas(64) float buf[kMaxSimdLanes];\n  alignas(64) float outResult[kMaxSimdLanes];\n\n  for (int32_t base = 0; base < numInputs; base += N) {\n    int32_t count = std::min(N, numInputs - base);\n    for (int32_t i = 0; i < count; ++i) {\n      buf[i] = kLdexpInputs[base + i];\n    }\n    for (int32_t i = count; i < N; ++i) {\n      buf[i] = buf[count - 1];\n    }\n\n    // Round-trip: frexp → ldexp should reproduce the input.\n    IntT exponent;\n    Flt mantissa = dfm::frexp(Traits::load(buf), &exponent);\n    Flt result = dfm::ldexp(mantissa, exponent);\n    Traits::store(result, outResult);\n\n    for (int32_t i = 0; i < count; ++i) {\n      if (std::isnan(buf[i])) {\n        EXPECT_TRUE(std::isnan(outResult[i])) << \"ldexp(frexp(NaN)) should be NaN\";\n      } else if (std::isinf(buf[i])) {\n        EXPECT_EQ(outResult[i], buf[i]) << \"ldexp(frexp(inf)) should be inf\";\n      } else {\n        EXPECT_EQ(outResult[i], buf[i])\n            << \"ldexp(frexp(\" << buf[i] << \")) round-trip mismatch: got \" << outResult[i];\n      }\n    }\n  }\n}\n\n#if defined(__SSE4_1__)\nTEST(LdexpSse, RoundTrip) {\n  checkLdexpSimd<__m128>();\n}\n#endif\n#if defined(__AVX2__)\nTEST(LdexpAvx, RoundTrip) {\n  checkLdexpSimd<__m256>();\n}\n#endif\n#if defined(__AVX512F__)\nTEST(LdexpAvx512, RoundTrip) {\n  checkLdexpSimd<__m512>();\n}\n#endif\n#if defined(__aarch64__)\nTEST(LdexpNeon, RoundTrip) {\n  checkLdexpSimd<float32x4_t>();\n}\n#endif\n#if __has_include(\"hwy/highway.h\")\nTEST(LdexpHwy, RoundTrip) {\n  checkLdexpSimd<dfm::HwyFloat>();\n}\n#endif\n"
  },
  {
    "path": "tests/fast_math/log10_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto log10_accurate = dispenso::fast_math::log10<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(Log10, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(log10_accurate(0.0f), -kInf);\n  EXPECT_NE(log10_accurate(-1.0f), log10_accurate(-1.0f));\n  EXPECT_EQ(log10_accurate(kInf), kInf);\n  EXPECT_NE(log10_accurate(kNaN), log10_accurate(kNaN));\n}\n\nTEST(Log10Accurate, RangeNeg) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::log10f, log10_accurate, 0.0f, 1.0f);\n  EXPECT_LE(res, 3u);\n}\n\nTEST(Log10Accurate, RangePos) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::log10f, log10_accurate, 1.0f);\n  EXPECT_LE(res, 3u);\n}\n\nTEST(Log10, RangeNeg) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(::log10f, dispenso::fast_math::log10<float>, 3e-38f, 1.0f);\n  EXPECT_LE(res, 3u);\n}\n\nTEST(Log10, RangePos) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(::log10f, dispenso::fast_math::log10<float>, 1.0f);\n  EXPECT_LE(res, 3u);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt log10_max(Flt x) {\n  return dfm::log10<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kLog10MaxUlps = 3;\nFAST_MATH_ACCURACY_TESTS(\n    Log10MaxAccAll,\n    ::log10f,\n    log10_max,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLog10MaxUlps)\nFAST_MATH_ACCURACY_TESTS(\n    Log10DefaultAll,\n    ::log10f,\n    dfm::log10,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLog10MaxUlps)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles out-of-domain inputs (0, negatives, NaN, Inf).\nstatic const float kLog10MaxAccSpecials[] = {\n    1.0f,\n    0.5f,\n    10.0f,\n    100.0f,\n    1000.0f,\n    0.1f,\n    0.01f,\n    0.0f,\n    -0.0f,\n    -1.0f,\n    -100.0f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(\n    Log10MaxAccSpecial,\n    ::log10f,\n    log10_max,\n    kLog10MaxAccSpecials,\n    kLog10MaxUlps)\n\n// Default traits only works for positive normal floats.\nstatic const float kLog10DefaultSpecials[] =\n    {1.0f, 0.5f, 10.0f, 100.0f, 1000.0f, 0.1f, 0.01f, 1e-10f, 10000.0f};\nFAST_MATH_SPECIAL_TESTS(\n    Log10DefaultSpecial,\n    ::log10f,\n    dfm::log10,\n    kLog10DefaultSpecials,\n    kLog10MaxUlps)\n"
  },
  {
    "path": "tests/fast_math/log1p_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nstatic float gt_log1p(float x) {\n  return static_cast<float>(std::log1p(static_cast<double>(x)));\n}\n\nTEST(Log1p, SpecialValues) {\n  EXPECT_EQ(dfm::log1p(0.0f), 0.0f);\n  EXPECT_FLOAT_EQ(dfm::log1p(1.0f), gt_log1p(1.0f));\n  EXPECT_FLOAT_EQ(dfm::log1p(-0.5f), gt_log1p(-0.5f));\n}\n\nTEST(Log1p, NearZero) {\n  // The primary use case: x very close to 0 where log(1+x) cancels.\n  float xs[] = {1e-7f, -1e-7f, 1e-5f, -1e-5f, 1e-3f, -1e-3f, 0.01f, -0.01f, 0.1f, -0.1f};\n  for (float x : xs) {\n    float expected = gt_log1p(x);\n    float result = dfm::log1p(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 2u) << \"log1p(\" << x << \"): expected=\" << expected << \" got=\" << result;\n  }\n}\n\nTEST(Log1p, RangeSmall) {\n  uint32_t ulps = dfm::evalAccuracy(gt_log1p, dfm::log1p<float>, -0.5f, 0.5f);\n  EXPECT_LE(ulps, 2u);\n}\n\nTEST(Log1p, RangeMedium) {\n  uint32_t ulps = dfm::evalAccuracy(gt_log1p, dfm::log1p<float>, -0.99f, 100.0f);\n  EXPECT_LE(ulps, 2u);\n}\n\nTEST(Log1p, RangeLarge) {\n  uint32_t ulps = dfm::evalAccuracy(gt_log1p, dfm::log1p<float>, -0.99f, 1e10f);\n  EXPECT_LE(ulps, 2u);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kLog1pMaxUlps = 2;\nFAST_MATH_ACCURACY_TESTS(Log1pAll, gt_log1p, dfm::log1p, -0.99f, 1e10f, kLog1pMaxUlps)\n\n// Special values tested across all SIMD backends.\n// log1p doesn't handle Inf — only test in-domain values.\nstatic const float kLog1pSpecials[] = {\n    0.0f,\n    -0.0f,\n    1.0f,\n    -0.5f,\n    0.5f,\n    10.0f,\n    100.0f,\n    0.001f,\n    -0.001f,\n    1e-4f,\n    -1e-4f,\n    1e-7f,\n    -1e-7f,\n    0.1f,\n    -0.1f,\n    1e-6f,\n    1e-3f};\nFAST_MATH_SPECIAL_TESTS(Log1pSpecial, gt_log1p, dfm::log1p, kLog1pSpecials, kLog1pMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/log2_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto log2_w_bounds = dispenso::fast_math::log2<float, dispenso::fast_math::MaxAccuracyTraits>;\n\n#ifdef _WIN32\nfloat groundTruth(float x) {\n  return static_cast<float>(::log2l(x));\n}\n#else\nauto groundTruth = ::log2f;\n#endif // _WIN32\n\nTEST(Log2, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(log2_w_bounds(0.0f), -kInf);\n  EXPECT_NE(log2_w_bounds(-1.0f), log2_w_bounds(-1.0f));\n  EXPECT_EQ(log2_w_bounds(kInf), kInf);\n  EXPECT_NE(log2_w_bounds(kNaN), log2_w_bounds(kNaN));\n\n  EXPECT_EQ(log2_w_bounds(1e-45f), groundTruth(1e-45f));\n}\n\nconstexpr int kNegUlps = 1;\nconstexpr int kPosUlps = 1;\n\nTEST(Log2WBounds, RangeNeg) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(groundTruth, log2_w_bounds, 0.0f, 1.0f);\n  EXPECT_LE(res, static_cast<uint32_t>(kNegUlps));\n}\n\nTEST(Log2WBounds, RangePos) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(groundTruth, log2_w_bounds, 1.0f);\n  EXPECT_LE(res, static_cast<uint32_t>(kPosUlps));\n}\n\nTEST(Log2, RangeNeg) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(\n      groundTruth, dispenso::fast_math::log2<float>, 3e-38f, 1.0f);\n  EXPECT_LE(res, static_cast<uint32_t>(kNegUlps));\n}\n\nTEST(Log2, RangePos) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(groundTruth, dispenso::fast_math::log2<float>, 1.0f);\n  EXPECT_LE(res, static_cast<uint32_t>(kPosUlps));\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt log2_max(Flt x) {\n  return dfm::log2<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kLog2MaxUlps = 1;\nFAST_MATH_ACCURACY_TESTS(\n    Log2MaxAccAll,\n    groundTruth,\n    log2_max,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLog2MaxUlps)\nFAST_MATH_ACCURACY_TESTS(\n    Log2DefaultAll,\n    groundTruth,\n    dfm::log2,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLog2MaxUlps)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles out-of-domain inputs (0, negatives, NaN, Inf).\nstatic const float kLog2MaxAccSpecials[] = {\n    1.0f,\n    0.5f,\n    2.0f,\n    4.0f,\n    8.0f,\n    16.0f,\n    1024.0f,\n    0.25f,\n    0.125f,\n    0.0f,\n    -0.0f,\n    -1.0f,\n    -100.0f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(Log2MaxAccSpecial, groundTruth, log2_max, kLog2MaxAccSpecials, kLog2MaxUlps)\n\n// Default traits only works for positive normal floats.\nstatic const float kLog2DefaultSpecials[] = {1.0f, 0.5f, 2.0f, 4.0f, 8.0f, 100.0f, 0.25f, 1e-10f};\nFAST_MATH_SPECIAL_TESTS(\n    Log2DefaultSpecial,\n    groundTruth,\n    dfm::log2,\n    kLog2DefaultSpecials,\n    kLog2MaxUlps)\n"
  },
  {
    "path": "tests/fast_math/log_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto log_accurate = dispenso::fast_math::log<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(Log, SpecialValues) {\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_EQ(log_accurate(0.0f), -kInf);\n  EXPECT_NE(log_accurate(-1.0f), log_accurate(-1.0f));\n  EXPECT_EQ(log_accurate(kInf), kInf);\n  EXPECT_NE(log_accurate(kNaN), log_accurate(kNaN));\n}\n\nTEST(LogAccurate, RangeNeg) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::logf, log_accurate, 0.0f, 1.0f);\n  EXPECT_LE(res, 2u);\n}\n\nTEST(LogAccurate, RangePos) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::logf, log_accurate, 1.0f);\n  EXPECT_LE(res, 2u);\n}\n\nTEST(Log, RangeNeg) {\n  uint32_t res =\n      dispenso::fast_math::evalAccuracy(::logf, dispenso::fast_math::log<float>, 3e-38f, 1.0f);\n  EXPECT_LE(res, 2u);\n}\n\nTEST(Log, RangePos) {\n  uint32_t res = dispenso::fast_math::evalAccuracy(::logf, dispenso::fast_math::log<float>, 1.0f);\n  EXPECT_LE(res, 2u);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt log_max(Flt x) {\n  return dfm::log<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kLogMaxUlps = 2;\nFAST_MATH_ACCURACY_TESTS(\n    LogMaxAccAll,\n    ::logf,\n    log_max,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLogMaxUlps)\nFAST_MATH_ACCURACY_TESTS(\n    LogDefaultAll,\n    ::logf,\n    dfm::log,\n    3e-38f,\n    std::numeric_limits<float>::max(),\n    kLogMaxUlps)\n\n// Special values tested across all SIMD backends.\n// MaxAccuracy handles out-of-domain inputs (0, negatives, NaN, Inf).\nstatic const float kLogMaxAccSpecials[] = {\n    1.0f,\n    0.5f,\n    2.0f,\n    10.0f,\n    100.0f,\n    0.01f,\n    1e-6f,\n    1e10f,\n    0.0f,\n    -0.0f,\n    -1.0f,\n    -100.0f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::max(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(LogMaxAccSpecial, ::logf, log_max, kLogMaxAccSpecials, kLogMaxUlps)\n\n// Default traits only works for positive normal floats.\nstatic const float kLogDefaultSpecials[] =\n    {1.0f, 0.5f, 2.0f, 10.0f, 100.0f, 0.01f, 1000.0f, 1e-10f, 1e6f};\nFAST_MATH_SPECIAL_TESTS(LogDefaultSpecial, ::logf, dfm::log, kLogDefaultSpecials, kLogMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/neon_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#if defined(__aarch64__)\n\n#include <arm_neon.h>\n\n#include <cmath>\n#include <limits>\n\n#include <dispenso/fast_math/fast_math.h>\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing NeonFloat = dfm::NeonFloat;\nusing NeonInt32 = dfm::NeonInt32;\nusing NeonUint32 = dfm::NeonUint32;\n\nconstexpr int kLanes = 4;\n\n// --- Lane extractors ---\n\nstatic float lane(float32x4_t v, int i) {\n  alignas(16) float buf[kLanes];\n  vst1q_f32(buf, v);\n  return buf[i];\n}\nstatic float lane(NeonFloat v, int i) {\n  return lane(v.v, i);\n}\n\nstatic int32_t lane(int32x4_t v, int i) {\n  alignas(16) int32_t buf[kLanes];\n  vst1q_s32(buf, v);\n  return buf[i];\n}\nstatic int32_t lane(NeonInt32 v, int i) {\n  return lane(v.v, i);\n}\n\nstatic uint32_t lane(uint32x4_t v, int i) {\n  alignas(16) uint32_t buf[kLanes];\n  vst1q_u32(buf, v);\n  return buf[i];\n}\nstatic uint32_t lane(NeonUint32 v, int i) {\n  return lane(v.v, i);\n}\n\n// --- Helpers ---\n\nstatic float32x4_t make4(float a, float b, float c, float d) {\n  float buf[4] = {a, b, c, d};\n  return vld1q_f32(buf);\n}\n\nstatic int32x4_t makeInt4(int32_t a, int32_t b, int32_t c, int32_t d) {\n  int32_t buf[4] = {a, b, c, d};\n  return vld1q_s32(buf);\n}\n\n// ==================== Basic Arithmetic ====================\n\nTEST(NeonFloat, Arithmetic) {\n  NeonFloat a(3.0f), b(2.0f);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a + b, i), 5.0f);\n    EXPECT_EQ(lane(a - b, i), 1.0f);\n    EXPECT_EQ(lane(a * b, i), 6.0f);\n    EXPECT_EQ(lane(a / b, i), 1.5f);\n  }\n}\n\nTEST(NeonFloat, Negation) {\n  NeonFloat a = make4(1.0f, -2.0f, 0.0f, 3.5f);\n  NeonFloat neg = -a;\n  EXPECT_EQ(lane(neg, 0), -1.0f);\n  EXPECT_EQ(lane(neg, 1), 2.0f);\n  EXPECT_FLOAT_EQ(lane(neg, 2), -0.0f);\n  EXPECT_EQ(lane(neg, 3), -3.5f);\n}\n\nTEST(NeonFloat, CompoundAssignment) {\n  NeonFloat a(10.0f), b(3.0f);\n  a += b;\n  for (int i = 0; i < kLanes; ++i)\n    EXPECT_EQ(lane(a, i), 13.0f);\n  a -= b;\n  for (int i = 0; i < kLanes; ++i)\n    EXPECT_EQ(lane(a, i), 10.0f);\n  a *= b;\n  for (int i = 0; i < kLanes; ++i)\n    EXPECT_EQ(lane(a, i), 30.0f);\n}\n\nTEST(NeonInt32, Arithmetic) {\n  NeonInt32 a(7), b(3);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a + b, i), 10);\n    EXPECT_EQ(lane(a - b, i), 4);\n    EXPECT_EQ(lane(a * b, i), 21);\n  }\n}\n\nTEST(NeonInt32, Negation) {\n  NeonInt32 a = makeInt4(5, -3, 0, 100);\n  NeonInt32 neg = -a;\n  EXPECT_EQ(lane(neg, 0), -5);\n  EXPECT_EQ(lane(neg, 1), 3);\n  EXPECT_EQ(lane(neg, 2), 0);\n  EXPECT_EQ(lane(neg, 3), -100);\n}\n\nTEST(NeonInt32, Shifts) {\n  NeonInt32 a(16);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a << 2, i), 64);\n    EXPECT_EQ(lane(a >> 2, i), 4);\n  }\n  // Arithmetic right shift preserves sign.\n  NeonInt32 neg(-16);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(neg >> 2, i), -4);\n  }\n}\n\nTEST(NeonUint32, Shifts) {\n  NeonUint32 a(16u);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(a << 2, i), 64u);\n    EXPECT_EQ(lane(a >> 2, i), 4u);\n  }\n  // Logical right shift (no sign extension).\n  NeonUint32 big(0x80000000u);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(big >> 1, i), 0x40000000u);\n  }\n}\n\n// ==================== Comparisons ====================\n\nTEST(NeonFloat, Comparisons) {\n  NeonFloat a = make4(1.0f, 2.0f, 3.0f, 4.0f);\n  NeonFloat b = make4(4.0f, 3.0f, 3.0f, 1.0f);\n\n  NeonFloat lt = a < b;\n  EXPECT_NE(lane(NeonInt32(bit_cast<NeonInt32>(lt)), 0), 0); // 1 < 4\n  EXPECT_NE(lane(NeonInt32(bit_cast<NeonInt32>(lt)), 1), 0); // 2 < 3\n  EXPECT_EQ(lane(NeonInt32(bit_cast<NeonInt32>(lt)), 2), 0); // 3 == 3\n  EXPECT_EQ(lane(NeonInt32(bit_cast<NeonInt32>(lt)), 3), 0); // 4 > 1\n}\n\nTEST(NeonInt32, Comparisons) {\n  NeonInt32 a = makeInt4(1, 5, -3, 0);\n  NeonInt32 b = makeInt4(2, 5, 0, -1);\n\n  NeonInt32 lt = a < b;\n  EXPECT_NE(lane(lt, 0), 0); // 1 < 2\n  EXPECT_EQ(lane(lt, 1), 0); // 5 == 5\n  EXPECT_NE(lane(lt, 2), 0); // -3 < 0\n  EXPECT_EQ(lane(lt, 3), 0); // 0 > -1\n\n  NeonInt32 eq = a == b;\n  EXPECT_EQ(lane(eq, 0), 0);\n  EXPECT_NE(lane(eq, 1), 0);\n  EXPECT_EQ(lane(eq, 2), 0);\n  EXPECT_EQ(lane(eq, 3), 0);\n}\n\nTEST(NeonUint32, UnsignedComparisons) {\n  NeonUint32 a(0x80000001u); // Large unsigned\n  NeonUint32 b(1u);\n  // a > b in unsigned (but would be negative in signed).\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_NE(lane(NeonUint32(a > b), i), 0u);\n    EXPECT_EQ(lane(NeonUint32(a < b), i), 0u);\n  }\n}\n\n// ==================== bit_cast ====================\n\nTEST(NeonBitCast, FloatIntRoundTrip) {\n  NeonFloat f = make4(1.0f, -2.0f, 0.0f, 3.14f);\n  NeonInt32 fi = dfm::bit_cast<NeonInt32>(f);\n  NeonFloat back = dfm::bit_cast<NeonFloat>(fi);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(back, i), lane(f, i));\n  }\n}\n\nTEST(NeonBitCast, FloatUintRoundTrip) {\n  NeonFloat f = make4(1.0f, -2.0f, 0.0f, 3.14f);\n  NeonUint32 fu = dfm::bit_cast<NeonUint32>(f);\n  NeonFloat back = dfm::bit_cast<NeonFloat>(fu);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(back, i), lane(f, i));\n  }\n}\n\nTEST(NeonBitCast, IntUintRoundTrip) {\n  NeonInt32 a = makeInt4(1, -1, 0, 0x7FFFFFFF);\n  NeonUint32 au = dfm::bit_cast<NeonUint32>(a);\n  NeonInt32 back = dfm::bit_cast<NeonInt32>(au);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(back, i), lane(a, i));\n  }\n}\n\n// ==================== FloatTraits ====================\n\nTEST(NeonFloatTraits, ConditionalWithMask) {\n  // Even lanes true, odd lanes false via float mask.\n  uint32_t mask_bits[4] = {0xFFFFFFFF, 0, 0xFFFFFFFF, 0};\n  NeonFloat mask = vreinterpretq_f32_u32(vld1q_u32(mask_bits));\n  NeonFloat x(10.0f);\n  NeonFloat y(20.0f);\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::conditional(mask, x, y);\n  EXPECT_EQ(lane(result, 0), 10.0f);\n  EXPECT_EQ(lane(result, 1), 20.0f);\n  EXPECT_EQ(lane(result, 2), 10.0f);\n  EXPECT_EQ(lane(result, 3), 20.0f);\n}\n\nTEST(NeonFloatTraits, ConditionalFromComparison) {\n  NeonFloat a = make4(1.0f, 5.0f, 10.0f, 15.0f);\n  NeonFloat threshold(8.0f);\n  auto mask = a > threshold;\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::conditional(mask, NeonFloat(100.0f), a);\n  EXPECT_EQ(lane(result, 0), 1.0f);\n  EXPECT_EQ(lane(result, 1), 5.0f);\n  EXPECT_EQ(lane(result, 2), 100.0f);\n  EXPECT_EQ(lane(result, 3), 100.0f);\n}\n\nTEST(NeonFloatTraits, ConditionalInt32WithMask) {\n  uint32_t mask_bits[4] = {0xFFFFFFFF, 0, 0xFFFFFFFF, 0};\n  NeonFloat mask = vreinterpretq_f32_u32(vld1q_u32(mask_bits));\n  NeonInt32 x(100);\n  NeonInt32 y(200);\n  NeonInt32 result = dfm::FloatTraits<NeonFloat>::conditional(mask, x, y);\n  EXPECT_EQ(lane(result, 0), 100);\n  EXPECT_EQ(lane(result, 1), 200);\n  EXPECT_EQ(lane(result, 2), 100);\n  EXPECT_EQ(lane(result, 3), 200);\n}\n\nTEST(NeonFloatTraits, ConditionalWithLaneWideMask) {\n  // Test the NeonInt32 mask overload.\n  NeonInt32 mask = makeInt4(-1, 0, -1, 0);\n  NeonFloat x(10.0f);\n  NeonFloat y(20.0f);\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::conditional(mask, x, y);\n  EXPECT_EQ(lane(result, 0), 10.0f);\n  EXPECT_EQ(lane(result, 1), 20.0f);\n  EXPECT_EQ(lane(result, 2), 10.0f);\n  EXPECT_EQ(lane(result, 3), 20.0f);\n}\n\nTEST(NeonFloatTraits, Apply) {\n  uint32_t mask_bits[4] = {0, 0, 0xFFFFFFFF, 0xFFFFFFFF};\n  NeonFloat mask = vreinterpretq_f32_u32(vld1q_u32(mask_bits));\n  NeonFloat x(42.0f);\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::apply(mask, x);\n  EXPECT_EQ(lane(result, 0), 0.0f);\n  EXPECT_EQ(lane(result, 1), 0.0f);\n  EXPECT_EQ(lane(result, 2), 42.0f);\n  EXPECT_EQ(lane(result, 3), 42.0f);\n}\n\nTEST(NeonFloatTraits, Fma) {\n  NeonFloat a(2.0f), b(3.0f), c(4.0f);\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::fma(a, b, c);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 10.0f) << \"Lane \" << i;\n  }\n}\n\nTEST(NeonFloatTraits, Sqrt) {\n  NeonFloat a = make4(4.0f, 9.0f, 16.0f, 25.0f);\n  NeonFloat result = dfm::FloatTraits<NeonFloat>::sqrt(a);\n  EXPECT_EQ(lane(result, 0), 2.0f);\n  EXPECT_EQ(lane(result, 1), 3.0f);\n  EXPECT_EQ(lane(result, 2), 4.0f);\n  EXPECT_EQ(lane(result, 3), 5.0f);\n}\n\nTEST(NeonFloatTraits, MinMax) {\n  NeonFloat a = make4(1.0f, 5.0f, 3.0f, 7.0f);\n  NeonFloat b = make4(4.0f, 2.0f, 3.0f, 8.0f);\n  NeonFloat mn = dfm::FloatTraits<NeonFloat>::min(a, b);\n  NeonFloat mx = dfm::FloatTraits<NeonFloat>::max(a, b);\n  EXPECT_EQ(lane(mn, 0), 1.0f);\n  EXPECT_EQ(lane(mn, 1), 2.0f);\n  EXPECT_EQ(lane(mn, 2), 3.0f);\n  EXPECT_EQ(lane(mn, 3), 7.0f);\n  EXPECT_EQ(lane(mx, 0), 4.0f);\n  EXPECT_EQ(lane(mx, 1), 5.0f);\n  EXPECT_EQ(lane(mx, 2), 3.0f);\n  EXPECT_EQ(lane(mx, 3), 8.0f);\n}\n\n// ==================== Util Functions ====================\n\nTEST(NeonUtil, FloorSmall) {\n  float32x4_t a = make4(1.5f, -1.5f, 2.0f, -0.1f);\n  auto result = dfm::floor_small(a);\n  EXPECT_EQ(lane(result, 0), 1.0f);\n  EXPECT_EQ(lane(result, 1), -2.0f);\n  EXPECT_EQ(lane(result, 2), 2.0f);\n  EXPECT_EQ(lane(result, 3), -1.0f);\n}\n\nTEST(NeonUtil, ConvertToInt) {\n  float32x4_t a = make4(1.5f, -1.5f, 2.4f, 3.6f);\n  auto result = dfm::convert_to_int(a);\n  // Round-to-nearest-even: 1.5→2, -1.5→-2, 2.4→2, 3.6→4\n  EXPECT_EQ(lane(result, 0), 2);\n  EXPECT_EQ(lane(result, 1), -2);\n  EXPECT_EQ(lane(result, 2), 2);\n  EXPECT_EQ(lane(result, 3), 4);\n}\n\nTEST(NeonUtil, ConvertToIntNaN) {\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float inf = std::numeric_limits<float>::infinity();\n  float32x4_t a = make4(nan, inf, -inf, 5.0f);\n  auto result = dfm::convert_to_int(a);\n  EXPECT_EQ(lane(result, 0), 0); // NaN → 0\n  EXPECT_EQ(lane(result, 1), 0); // Inf → 0\n  EXPECT_EQ(lane(result, 2), 0); // -Inf → 0\n  EXPECT_EQ(lane(result, 3), 5); // Normal\n}\n\nTEST(NeonUtil, Gather) {\n  float table[] = {10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f};\n  int32x4_t index = makeInt4(3, 0, 7, 1);\n  auto result = dfm::gather<NeonFloat>(table, index);\n  EXPECT_EQ(lane(result, 0), 40.0f);\n  EXPECT_EQ(lane(result, 1), 10.0f);\n  EXPECT_EQ(lane(result, 2), 80.0f);\n  EXPECT_EQ(lane(result, 3), 20.0f);\n}\n\nTEST(NeonUtil, IntDivBy3) {\n  int32x4_t a = makeInt4(0, 3, 9, 99);\n  auto result = dfm::int_div_by_3(a);\n  int32_t inputs[] = {0, 3, 9, 99};\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), inputs[i] / 3) << \"Lane \" << i << \" input=\" << inputs[i];\n  }\n}\n\nTEST(NeonUtil, Signof) {\n  float32x4_t a = make4(1.0f, -1.0f, 0.0f, -0.0f);\n  auto result = dfm::signof(a);\n  EXPECT_EQ(lane(result, 0), 1.0f);\n  EXPECT_EQ(lane(result, 1), -1.0f);\n  EXPECT_EQ(lane(result, 2), 1.0f);\n  EXPECT_EQ(lane(result, 3), -1.0f);\n}\n\nTEST(NeonUtil, Signofi) {\n  int32x4_t a = makeInt4(5, -3, 0, -100);\n  auto result = dfm::signofi<NeonFloat>(a);\n  EXPECT_EQ(lane(result, 0), 1);\n  EXPECT_EQ(lane(result, 1), -1);\n  EXPECT_EQ(lane(result, 2), 1);\n  EXPECT_EQ(lane(result, 3), -1);\n}\n\nTEST(NeonUtil, Nonnormal) {\n  float inf = std::numeric_limits<float>::infinity();\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float32x4_t a = make4(1.0f, inf, nan, 0.0f);\n  auto result = dfm::nonnormal(NeonFloat(a));\n  EXPECT_EQ(lane(result, 0), 0); // Normal\n  EXPECT_NE(lane(result, 1), 0); // Inf\n  EXPECT_NE(lane(result, 2), 0); // NaN\n  EXPECT_EQ(lane(result, 3), 0); // Zero\n}\n\nTEST(NeonUtil, NonnormalOrZero) {\n  float inf = std::numeric_limits<float>::infinity();\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float32x4_t a = make4(1.0f, inf, nan, 0.0f);\n  NeonInt32 fi = dfm::bit_cast<NeonInt32>(NeonFloat(a));\n  auto result = dfm::nonnormalOrZero<NeonFloat>(fi);\n  EXPECT_EQ(lane(result, 0), 0); // Normal\n  EXPECT_NE(lane(result, 1), 0); // Inf\n  EXPECT_NE(lane(result, 2), 0); // NaN\n  EXPECT_NE(lane(result, 3), 0); // Zero\n}\n\nTEST(NeonUtil, BoolAsOne) {\n  NeonFloat mask = NeonFloat(1.0f) > NeonFloat(0.0f); // All true\n  NeonFloat result = dfm::bool_as_one<NeonFloat, NeonFloat>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 1.0f);\n  }\n\n  NeonFloat false_mask = NeonFloat(0.0f) > NeonFloat(1.0f); // All false\n  NeonFloat result2 = dfm::bool_as_one<NeonFloat, NeonFloat>(false_mask);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result2, i), 0.0f);\n  }\n}\n\nTEST(NeonUtil, NboolAsOne) {\n  NeonFloat mask = NeonFloat(1.0f) > NeonFloat(0.0f); // All true\n  NeonFloat result = dfm::nbool_as_one<NeonFloat, NeonFloat>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), 0.0f); // nbool: true → 0\n  }\n\n  NeonFloat false_mask = NeonFloat(0.0f) > NeonFloat(1.0f); // All false\n  NeonFloat result2 = dfm::nbool_as_one<NeonFloat, NeonFloat>(false_mask);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result2, i), 1.0f); // nbool: false → 1\n  }\n}\n\nTEST(NeonUtil, BoolAsMask) {\n  NeonFloat mask = NeonFloat(1.0f) > NeonFloat(0.0f); // All true = 0xFFFFFFFF\n  NeonInt32 result = dfm::bool_as_mask<NeonInt32, NeonFloat>(mask);\n  for (int i = 0; i < kLanes; ++i) {\n    EXPECT_EQ(lane(result, i), -1);\n  }\n}\n\nTEST(NeonUtil, BoolApplyOrZero) {\n  NeonFloat mask = NeonFloat(make4(1.0f, 0.0f, 3.0f, 0.0f)) > NeonFloat(0.5f);\n  NeonFloat val(42.0f);\n  NeonFloat result = dfm::bool_apply_or_zero(mask, val);\n  EXPECT_EQ(lane(result, 0), 42.0f);\n  EXPECT_EQ(lane(result, 1), 0.0f);\n  EXPECT_EQ(lane(result, 2), 42.0f);\n  EXPECT_EQ(lane(result, 3), 0.0f);\n}\n\nTEST(NeonUtil, ClampAllowNan) {\n  float32x4_t x = make4(-5.0f, 0.5f, 10.0f, 0.5f);\n  auto result = dfm::clamp_allow_nan(NeonFloat(x), NeonFloat(0.0f), NeonFloat(1.0f));\n  EXPECT_EQ(lane(result, 0), 0.0f);\n  EXPECT_EQ(lane(result, 1), 0.5f);\n  EXPECT_EQ(lane(result, 2), 1.0f);\n  EXPECT_EQ(lane(result, 3), 0.5f);\n\n  // NaN propagates.\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float32x4_t nan_x = make4(nan, 0.5f, nan, 0.5f);\n  auto nan_result = dfm::clamp_allow_nan(NeonFloat(nan_x), NeonFloat(0.0f), NeonFloat(1.0f));\n  EXPECT_TRUE(std::isnan(lane(nan_result, 0)));\n  EXPECT_EQ(lane(nan_result, 1), 0.5f);\n  EXPECT_TRUE(std::isnan(lane(nan_result, 2)));\n  EXPECT_EQ(lane(nan_result, 3), 0.5f);\n}\n\nTEST(NeonUtil, ClampNoNan) {\n  float32x4_t x = make4(-5.0f, 0.5f, 10.0f, 0.5f);\n  auto result = dfm::clamp_no_nan(NeonFloat(x), NeonFloat(0.0f), NeonFloat(1.0f));\n  EXPECT_EQ(lane(result, 0), 0.0f);\n  EXPECT_EQ(lane(result, 1), 0.5f);\n  EXPECT_EQ(lane(result, 2), 1.0f);\n  EXPECT_EQ(lane(result, 3), 0.5f);\n\n  // NaN is suppressed — result must be in [mn, mx].\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float32x4_t nan_x = make4(nan, 0.5f, nan, 0.5f);\n  auto nan_result = dfm::clamp_no_nan(NeonFloat(nan_x), NeonFloat(0.0f), NeonFloat(1.0f));\n  EXPECT_FALSE(std::isnan(lane(nan_result, 0)));\n  EXPECT_GE(lane(nan_result, 0), 0.0f);\n  EXPECT_LE(lane(nan_result, 0), 1.0f);\n  EXPECT_EQ(lane(nan_result, 1), 0.5f);\n  EXPECT_FALSE(std::isnan(lane(nan_result, 2)));\n  EXPECT_EQ(lane(nan_result, 3), 0.5f);\n}\n\n#endif // defined(__aarch64__)\n"
  },
  {
    "path": "tests/fast_math/pow_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <cmath>\n#include <random>\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\n// Ground truth: double-precision pow, rounded to float.\nstatic float gt_pow(float x, float y) {\n  return static_cast<float>(std::pow(static_cast<double>(x), static_cast<double>(y)));\n}\n\n// --- Accuracy tests ---\n\nTEST(Pow, SpecialValues) {\n  auto pow_f = dfm::pow<float>;\n  EXPECT_EQ(pow_f(2.0f, 10.0f), 1024.0f);\n  EXPECT_EQ(pow_f(0.5f, 2.0f), 0.25f);\n  EXPECT_EQ(pow_f(4.0f, 0.5f), 2.0f);\n  EXPECT_NEAR(pow_f(8.0f, 1.0f / 3.0f), 2.0f, 1e-6f);\n  EXPECT_NEAR(pow_f(10.0f, -1.0f), 0.1f, 1e-7f);\n}\n\nTEST(Pow, ExactIntegerPowers) {\n  // pow(2, n) for small n should be exact or near-exact.\n  for (int32_t n = 1; n <= 23; ++n) {\n    float expected = static_cast<float>(1 << n);\n    float result = dfm::pow(2.0f, static_cast<float>(n));\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 1u) << \"pow(2, \" << n << \"): expected=\" << expected << \" got=\" << result;\n  }\n  // pow(3, n) for small n.\n  float p3 = 1.0f;\n  for (int32_t n = 1; n <= 14; ++n) {\n    p3 *= 3.0f;\n    float result = dfm::pow(3.0f, static_cast<float>(n));\n    uint32_t dist = dfm::float_distance(p3, result);\n    EXPECT_LE(dist, 2u) << \"pow(3, \" << n << \"): expected=\" << p3 << \" got=\" << result;\n  }\n}\n\nTEST(Pow, RandomModerate) {\n  std::mt19937 rng(42);\n  std::uniform_real_distribution<float> x_dist(0.01f, 100.0f);\n  std::uniform_real_distribution<float> y_dist(-8.0f, 8.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::pow(x, y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  // Default path now uses double-precision core: <1 ULP for float output.\n  EXPECT_LE(maxUlps, 4u) << \"RandomModerate max ULP\";\n}\n\nTEST(Pow, RandomWide) {\n  std::mt19937 rng(123);\n  std::uniform_real_distribution<float> x_dist(1e-10f, 1e10f);\n  std::uniform_real_distribution<float> y_dist(-4.0f, 4.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::pow(x, y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  EXPECT_LE(maxUlps, 4u) << \"RandomWide max ULP\";\n}\n\nTEST(Pow, RandomSmallExp) {\n  std::mt19937 rng(7);\n  std::uniform_real_distribution<float> x_dist(0.5f, 2.0f);\n  std::uniform_real_distribution<float> y_dist(-1.0f, 1.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::pow(x, y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  EXPECT_LE(maxUlps, 3u) << \"RandomSmallExp max ULP\";\n}\n\n// --- Negative base tests ---\n\nTEST(Pow, NegativeBaseIntegerExp) {\n  // pow(neg, even) → positive, pow(neg, odd) → negative.\n  float bases[] = {-0.5f, -1.0f, -2.0f, -100.0f};\n  float exps[] = {2.0f, 3.0f, 4.0f, 5.0f, -1.0f, -2.0f, -3.0f};\n\n  for (float x : bases) {\n    for (float y : exps) {\n      float expected = gt_pow(x, y);\n      float result = dfm::pow<float, dfm::MaxAccuracyTraits>(x, y);\n      if (std::isnan(expected)) {\n        EXPECT_TRUE(std::isnan(result)) << \"pow(\" << x << \", \" << y << \")\";\n      } else if (std::isinf(expected)) {\n        EXPECT_TRUE(std::isinf(result)) << \"pow(\" << x << \", \" << y << \")\";\n        EXPECT_EQ(std::signbit(expected), std::signbit(result))\n            << \"pow(\" << x << \", \" << y << \") sign mismatch\";\n      } else {\n        uint32_t dist = dfm::float_distance(expected, result);\n        EXPECT_LE(dist, 3u) << \"pow(\" << x << \", \" << y << \"): expected=\" << expected\n                            << \" got=\" << result;\n        // Check sign correctness.\n        EXPECT_EQ(std::signbit(expected), std::signbit(result))\n            << \"pow(\" << x << \", \" << y << \") sign mismatch\";\n      }\n    }\n  }\n}\n\nTEST(Pow, NegativeBaseNonIntegerExp) {\n  // pow(negative, non-integer) → NaN.\n  float bases[] = {-1.0f, -2.0f, -0.5f};\n  float exps[] = {0.5f, 1.5f, -0.5f, 2.7f};\n\n  for (float x : bases) {\n    for (float y : exps) {\n      float result = dfm::pow<float, dfm::MaxAccuracyTraits>(x, y);\n      EXPECT_TRUE(std::isnan(result))\n          << \"pow(\" << x << \", \" << y << \") should be NaN, got \" << result;\n    }\n  }\n}\n\nTEST(Pow, NegativeBaseRandomInteger) {\n  std::mt19937 rng(999);\n  std::uniform_real_distribution<float> x_dist(-100.0f, -0.01f);\n\n  uint32_t maxUlps = 0;\n  for (int32_t y_int = -50; y_int <= 50; ++y_int) {\n    float y = static_cast<float>(y_int);\n    for (int32_t i = 0; i < 1024; ++i) {\n      float x = x_dist(rng);\n      float expected = gt_pow(x, y);\n      float result = dfm::pow<float, dfm::MaxAccuracyTraits>(x, y);\n      if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n        continue;\n      }\n      uint32_t dist = dfm::float_distance(expected, result);\n      maxUlps = std::max(maxUlps, dist);\n    }\n  }\n  // MaxAccuracy with negative base goes through exp2(y * log2(|x|)) + sign XOR.\n  // For y up to 50 and large |x|, error can reach ~10 ULP.\n  EXPECT_LE(maxUlps, 16u) << \"NegativeBaseRandomInteger max ULP\";\n}\n\n// --- IEEE 754 boundary conditions (MaxAccuracyTraits) ---\n\nTEST(PowBounds, YZero) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  // pow(x, 0) = 1 for all x.\n  float xs[] = {0.0f, -0.0f, 1.0f, -1.0f, kInf, -kInf, kNaN, 42.0f, -42.0f};\n  for (float x : xs) {\n    EXPECT_EQ(pow_b(x, 0.0f), 1.0f) << \"pow(\" << x << \", 0) should be 1\";\n  }\n}\n\nTEST(PowBounds, XOne) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  // pow(1, y) = 1 for all y, even NaN.\n  float ys[] = {0.0f, 1.0f, -1.0f, kInf, -kInf, kNaN, 42.0f};\n  for (float y : ys) {\n    EXPECT_EQ(pow_b(1.0f, y), 1.0f) << \"pow(1, \" << y << \") should be 1\";\n  }\n}\n\nTEST(PowBounds, NegOneInf) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n\n  EXPECT_EQ(pow_b(-1.0f, kInf), 1.0f) << \"pow(-1, +inf) should be 1\";\n  EXPECT_EQ(pow_b(-1.0f, -kInf), 1.0f) << \"pow(-1, -inf) should be 1\";\n}\n\nTEST(PowBounds, ZeroPosExp) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n\n  EXPECT_EQ(pow_b(0.0f, 1.0f), 0.0f);\n  EXPECT_FALSE(std::signbit(pow_b(0.0f, 1.0f)));\n  EXPECT_EQ(pow_b(0.0f, 2.0f), 0.0f);\n  EXPECT_EQ(pow_b(0.0f, 0.5f), 0.0f);\n\n  EXPECT_EQ(pow_b(-0.0f, 1.0f), -0.0f);\n  EXPECT_TRUE(std::signbit(pow_b(-0.0f, 1.0f)));\n  EXPECT_EQ(pow_b(-0.0f, 3.0f), -0.0f);\n  EXPECT_TRUE(std::signbit(pow_b(-0.0f, 3.0f)));\n  EXPECT_EQ(pow_b(-0.0f, 2.0f), 0.0f);\n  EXPECT_FALSE(std::signbit(pow_b(-0.0f, 2.0f)));\n  EXPECT_EQ(pow_b(-0.0f, 0.5f), 0.0f);\n}\n\nTEST(PowBounds, ZeroNegExp) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n\n  EXPECT_EQ(pow_b(0.0f, -1.0f), kInf);\n  EXPECT_EQ(pow_b(0.0f, -2.0f), kInf);\n  EXPECT_EQ(pow_b(-0.0f, -1.0f), -kInf);\n  EXPECT_EQ(pow_b(-0.0f, -3.0f), -kInf);\n  EXPECT_EQ(pow_b(-0.0f, -2.0f), kInf);\n}\n\nTEST(PowBounds, InfPosExp) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n\n  EXPECT_EQ(pow_b(kInf, 1.0f), kInf);\n  EXPECT_EQ(pow_b(kInf, 2.0f), kInf);\n  EXPECT_EQ(pow_b(-kInf, 1.0f), -kInf);\n  EXPECT_EQ(pow_b(-kInf, 3.0f), -kInf);\n  EXPECT_EQ(pow_b(-kInf, 2.0f), kInf);\n}\n\nTEST(PowBounds, InfNegExp) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n\n  EXPECT_EQ(pow_b(kInf, -1.0f), 0.0f);\n  EXPECT_FALSE(std::signbit(pow_b(kInf, -1.0f)));\n  EXPECT_EQ(pow_b(kInf, -2.0f), 0.0f);\n\n  EXPECT_EQ(pow_b(-kInf, -1.0f), -0.0f);\n  EXPECT_TRUE(std::signbit(pow_b(-kInf, -1.0f)));\n  EXPECT_EQ(pow_b(-kInf, -3.0f), -0.0f);\n  EXPECT_TRUE(std::signbit(pow_b(-kInf, -3.0f)));\n  EXPECT_EQ(pow_b(-kInf, -2.0f), 0.0f);\n  EXPECT_FALSE(std::signbit(pow_b(-kInf, -2.0f)));\n}\n\nTEST(PowBounds, AbsXInf) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kInf = std::numeric_limits<float>::infinity();\n\n  EXPECT_EQ(pow_b(0.5f, -kInf), kInf);\n  EXPECT_EQ(pow_b(2.0f, -kInf), 0.0f);\n  EXPECT_EQ(pow_b(0.5f, kInf), 0.0f);\n  EXPECT_EQ(pow_b(2.0f, kInf), kInf);\n}\n\nTEST(PowBounds, NaNPropagation) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_TRUE(std::isnan(pow_b(kNaN, 2.0f)));\n  EXPECT_TRUE(std::isnan(pow_b(2.0f, kNaN)));\n  EXPECT_TRUE(std::isnan(pow_b(kNaN, kNaN)));\n  EXPECT_TRUE(std::isnan(pow_b(-2.0f, 1.5f)));\n}\n\nTEST(PowBounds, Subnormal) {\n  auto pow_b = dfm::pow<float, dfm::MaxAccuracyTraits>;\n  // Subnormal bases: fp32 subnormals are in [1.4e-45, 1.2e-38].\n  float subnormals[] = {1.0e-40f, 1.0e-42f, 1.0e-44f, std::numeric_limits<float>::denorm_min()};\n  float exps[] = {2.0f, 0.5f, -1.0f, 3.0f};\n\n  for (float x : subnormals) {\n    for (float y : exps) {\n      float expected = gt_pow(x, y);\n      float result = pow_b(x, y);\n      if (std::isnan(expected)) {\n        EXPECT_TRUE(std::isnan(result)) << \"pow(\" << x << \", \" << y << \")\";\n      } else if (std::isinf(expected)) {\n        EXPECT_TRUE(std::isinf(result))\n            << \"pow(\" << x << \", \" << y << \") expected inf, got \" << result;\n      } else if (expected == 0.0f) {\n        EXPECT_EQ(result, 0.0f) << \"pow(\" << x << \", \" << y << \") expected 0, got \" << result;\n      } else {\n        uint32_t dist = dfm::float_distance(expected, result);\n        EXPECT_LE(dist, 4u) << \"pow(\" << x << \", \" << y << \"): expected=\" << expected\n                            << \" got=\" << result;\n      }\n    }\n  }\n}\n\n// --- MaxAccuracy random tests ---\n\nTEST(PowAccurate, RandomModerate) {\n  std::mt19937 rng(42);\n  std::uniform_real_distribution<float> x_dist(0.01f, 100.0f);\n  std::uniform_real_distribution<float> y_dist(-8.0f, 8.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::pow<float, dfm::MaxAccuracyTraits>(x, y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  EXPECT_LE(maxUlps, 3u) << \"MaxAccuracy RandomModerate max ULP\";\n}\n\nTEST(PowDouble, RandomModerate) {\n  std::mt19937 rng(42);\n  std::uniform_real_distribution<float> x_dist(0.01f, 100.0f);\n  std::uniform_real_distribution<float> y_dist(-8.0f, 8.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::detail::pow_double_core(std::fabs(x), y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  EXPECT_LE(maxUlps, 4u) << \"PowDouble RandomModerate max ULP\";\n}\n\nTEST(PowDouble, RandomWide) {\n  std::mt19937 rng(123);\n  std::uniform_real_distribution<float> x_dist(1e-10f, 1e10f);\n  std::uniform_real_distribution<float> y_dist(-4.0f, 4.0f);\n\n  uint32_t maxUlps = 0;\n  constexpr int32_t kN = 1 << 20;\n  for (int32_t i = 0; i < kN; ++i) {\n    float x = x_dist(rng);\n    float y = y_dist(rng);\n    float expected = gt_pow(x, y);\n    float result = dfm::detail::pow_double_core(std::fabs(x), y);\n    if (std::isnan(expected) || std::isinf(expected) || expected == 0.0f) {\n      continue;\n    }\n    uint32_t dist = dfm::float_distance(expected, result);\n    maxUlps = std::max(maxUlps, dist);\n  }\n  EXPECT_LE(maxUlps, 4u) << \"PowDouble RandomWide max ULP\";\n}\n\n// Wrappers for traits variants — macro instantiates func<Flt>.\n// Wrappers needed because pow has (Flt, Flt) and (Flt, float) overloads.\ntemplate <typename Flt>\nFlt pow_default(Flt x, Flt y) {\n  return dfm::pow<Flt>(x, y);\n}\n\ntemplate <typename Flt>\nFlt pow_max(Flt x, Flt y) {\n  return dfm::pow<Flt, dfm::MaxAccuracyTraits>(x, y);\n}\n\n// Default pow — positive bases, normal range.\nconstexpr uint32_t kPowDefaultUlps = 4;\n// clang-format off\nstatic const float kPowDefaultX[] = {\n    2.0f, 3.0f, 4.0f, 0.5f,\n    2.0f, 10.0f, 100.0f, 0.01f,\n    1.0f, 0.5f, 2.0f};\nstatic const float kPowDefaultY[] = {\n    3.0f, 2.0f, 0.5f, -1.0f,\n    10.0f, -1.0f, 0.5f, 2.0f,\n    42.0f, -1.0f, 2.5f};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    PowDefaultSpecial,\n    gt_pow,\n    pow_default,\n    kPowDefaultX,\n    kPowDefaultY,\n    kPowDefaultUlps)\n\n// MaxAccuracy handles negative bases, zero, inf, NaN, subnormals.\nconstexpr uint32_t kPowMaxAccUlps = 4;\n// clang-format off\nstatic const float kPowMaxAccX[] = {\n    2.0f, 3.0f, 4.0f, 0.5f,                                            // basic powers\n    -2.0f, -1.0f, -3.0f, -0.5f,                                        // neg base int exp\n    -2.0f, -1.0f,                                                       // neg base non-int → NaN\n    0.0f, -0.0f, 0.0f, -0.0f,                                          // zero base\n    std::numeric_limits<float>::infinity(),                              // inf base\n    -std::numeric_limits<float>::infinity(),\n    std::numeric_limits<float>::infinity(),\n    1.0f, 1.0f,                                                         // x=1 → always 1\n    2.0f, std::numeric_limits<float>::quiet_NaN(),                      // NaN\n    -1.0f, -1.0f,                                                       // pow(-1, ±inf) = 1\n    0.5f, 2.0f};                                                        // |x| vs inf exp\nstatic const float kPowMaxAccY[] = {\n    3.0f, 2.0f, 0.5f, -1.0f,\n    3.0f, 2.0f, 5.0f, -1.0f,\n    0.5f, 1.5f,\n    2.0f, 3.0f, -1.0f, -1.0f,\n    2.0f,\n    3.0f,\n    -1.0f,\n    42.0f, std::numeric_limits<float>::quiet_NaN(),\n    0.0f, 2.0f,\n    std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity()};\n// clang-format on\nFAST_MATH_SPECIAL_TESTS_2ARG(\n    PowMaxAccSpecial,\n    gt_pow,\n    pow_max,\n    kPowMaxAccX,\n    kPowMaxAccY,\n    kPowMaxAccUlps)\n"
  },
  {
    "path": "tests/fast_math/pow_ulp_eval.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Exhaustive ULP evaluation for fast_math::pow across scalar and SIMD backends.\n// Uses Halton low-discrepancy sampling over 2D (base, exponent) domains.\n//\n// Usage: buck run <target> [-- [--samples N] [--filter name]]\n\n#include <cmath>\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"bivariate_ulp_eval.h\"\n\nnamespace dfm = dispenso::fast_math;\n\n// --- Ground truth (double-precision internally) ---\n\nstatic float gt_pow(float x, float y) {\n  return static_cast<float>(std::pow(static_cast<double>(x), static_cast<double>(y)));\n}\n\n// --- Domains ---\n// Positive bases only (negative base + non-integer exp is NaN by definition).\n\nstatic dfm::Domain2D kPowDomains[] = {\n    {0.01f, 100.0f, -8.0f, 8.0f, \"moderate base, moderate exp\"},\n    {1e-10f, 1e10f, -4.0f, 4.0f, \"wide base, small exp\"},\n    {0.5f, 2.0f, -50.0f, 50.0f, \"near-unity base, large exp\"},\n    {1e-6f, 1e-1f, 0.1f, 4.0f, \"small base, positive exp\"},\n    {1e2f, 1e20f, -2.0f, 2.0f, \"large base, small exp\"},\n    {0.01f, 100.0f, 1.0f, 50.0f, \"moderate base, integer-like exp\"},\n};\n\n// --- Batch runners ---\n\nstatic void pow_scalar(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; ++i)\n    out[i] = dfm::pow(xs[i], ys[i]);\n}\n\nstatic void pow_scalar_accurate(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; ++i)\n    out[i] = dfm::pow<float, dfm::MaxAccuracyTraits>(xs[i], ys[i]);\n}\n\n#if defined(__SSE4_1__)\nstatic void pow_sse(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 4) {\n    dfm::SseFloat vx{_mm_load_ps(&xs[i])};\n    dfm::SseFloat vy{_mm_load_ps(&ys[i])};\n    dfm::SseFloat vr = dfm::pow(vx, vy);\n    _mm_store_ps(&out[i], vr.v);\n  }\n}\n\nstatic void pow_sse_accurate(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 4) {\n    dfm::SseFloat vx{_mm_load_ps(&xs[i])};\n    dfm::SseFloat vy{_mm_load_ps(&ys[i])};\n    dfm::SseFloat vr = dfm::pow<dfm::SseFloat, dfm::MaxAccuracyTraits>(vx, vy);\n    _mm_store_ps(&out[i], vr.v);\n  }\n}\n#endif // __SSE4_1__\n\n#if defined(__AVX2__)\nstatic void pow_avx(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 8) {\n    dfm::AvxFloat vx{_mm256_load_ps(&xs[i])};\n    dfm::AvxFloat vy{_mm256_load_ps(&ys[i])};\n    dfm::AvxFloat vr = dfm::pow(vx, vy);\n    _mm256_store_ps(&out[i], vr.v);\n  }\n}\n\nstatic void pow_avx_accurate(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 8) {\n    dfm::AvxFloat vx{_mm256_load_ps(&xs[i])};\n    dfm::AvxFloat vy{_mm256_load_ps(&ys[i])};\n    dfm::AvxFloat vr = dfm::pow<dfm::AvxFloat, dfm::MaxAccuracyTraits>(vx, vy);\n    _mm256_store_ps(&out[i], vr.v);\n  }\n}\n#endif // __AVX2__\n\n#if defined(__AVX512F__)\nstatic void pow_avx512(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 16) {\n    dfm::Avx512Float vx{_mm512_load_ps(&xs[i])};\n    dfm::Avx512Float vy{_mm512_load_ps(&ys[i])};\n    dfm::Avx512Float vr = dfm::pow(vx, vy);\n    _mm512_store_ps(&out[i], vr.v);\n  }\n}\n\nstatic void pow_avx512_accurate(const float* xs, const float* ys, float* out, int32_t n) {\n  for (int32_t i = 0; i < n; i += 16) {\n    dfm::Avx512Float vx{_mm512_load_ps(&xs[i])};\n    dfm::Avx512Float vy{_mm512_load_ps(&ys[i])};\n    dfm::Avx512Float vr = dfm::pow<dfm::Avx512Float, dfm::MaxAccuracyTraits>(vx, vy);\n    _mm512_store_ps(&out[i], vr.v);\n  }\n}\n#endif // __AVX512F__\n\n// --- Main ---\n\nint main(int argc, char** argv) {\n  auto opts = dfm::parseEvalOptions(argc, argv);\n  uint64_t n = opts.numSamples;\n\n  printf(\n      \"pow ULP evaluation — %llu Halton samples per domain\\n\\n\",\n      static_cast<unsigned long long>(n));\n\n  if (dfm::shouldRun(opts, \"scalar\")) {\n    printf(\"=== pow scalar ===\\n\");\n    dfm::evalFunc2D(\"pow scalar\", gt_pow, pow_scalar, kPowDomains, n);\n    printf(\"\\n\");\n    printf(\"=== pow scalar MaxAccuracy ===\\n\");\n    dfm::evalFunc2D(\"pow scalar accurate\", gt_pow, pow_scalar_accurate, kPowDomains, n);\n    printf(\"\\n\");\n  }\n\n#if defined(__SSE4_1__)\n  if (dfm::shouldRun(opts, \"sse\")) {\n    printf(\"=== pow SSE ===\\n\");\n    dfm::evalFunc2D(\"pow SSE\", gt_pow, pow_sse, kPowDomains, n);\n    printf(\"\\n\");\n    printf(\"=== pow SSE MaxAccuracy ===\\n\");\n    dfm::evalFunc2D(\"pow SSE accurate\", gt_pow, pow_sse_accurate, kPowDomains, n);\n    printf(\"\\n\");\n  }\n#endif\n\n#if defined(__AVX2__)\n  if (dfm::shouldRun(opts, \"avx\")) {\n    printf(\"=== pow AVX ===\\n\");\n    dfm::evalFunc2D(\"pow AVX\", gt_pow, pow_avx, kPowDomains, n);\n    printf(\"\\n\");\n    printf(\"=== pow AVX MaxAccuracy ===\\n\");\n    dfm::evalFunc2D(\"pow AVX accurate\", gt_pow, pow_avx_accurate, kPowDomains, n);\n    printf(\"\\n\");\n  }\n#endif\n\n#if defined(__AVX512F__)\n  if (dfm::shouldRun(opts, \"avx512\")) {\n    printf(\"=== pow AVX-512 ===\\n\");\n    dfm::evalFunc2D(\"pow AVX-512\", gt_pow, pow_avx512, kPowDomains, n);\n    printf(\"\\n\");\n    printf(\"=== pow AVX-512 MaxAccuracy ===\\n\");\n    dfm::evalFunc2D(\"pow AVX-512 accurate\", gt_pow, pow_avx512_accurate, kPowDomains, n);\n    printf(\"\\n\");\n  }\n#endif\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/fast_math/simd_test_utils.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Unified test infrastructure for fast_math functions across scalar and SIMD.\n//\n// Provides:\n//   - SimdTestTraits<Flt>: lane count, load/store, lane extraction for any Flt type\n//   - evalAccuracy<Flt>(): exhaustive accuracy evaluator that works identically for\n//     scalar (float) and SIMD types — same function, same threshold, same call site\n//   - checkLaneByLane<Flt>(): verify specific inputs against scalar ground truth\n//   - FAST_MATH_ACCURACY_TESTS(): macro that generates one test per available backend,\n//     all sharing a single ULP threshold (the source of truth)\n//\n// Usage:\n//   #include \"simd_test_utils.h\"\n//   using namespace dispenso::fast_math::testing;\n//\n//   static float gt_sin(float x) { return ::sinf(x); }\n//   constexpr uint32_t kSinUlps = 1;\n//   FAST_MATH_ACCURACY_TESTS(Sin, gt_sin, dfm::sin, -128*kPi, 128*kPi, kSinUlps)\n\n#pragma once\n\n#include <cmath>\n#include <cstdint>\n#include <cstdio>\n#include <limits>\n\n#include <dispenso/fast_math/fast_math.h>\n#include <dispenso/fast_math/util.h>\n\n#include \"eval.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dispenso {\nnamespace fast_math {\nnamespace testing {\n\n// ---------------------------------------------------------------------------\n// SimdTestTraits<Flt> — lane count, load, store, lane extraction.\n// ---------------------------------------------------------------------------\n\n// Maximum lane count we'll ever encounter (2048-bit vectors).\nconstexpr int32_t kMaxSimdLanes = 64;\n\n// Primary template: scalar float.\ntemplate <typename Flt>\nstruct SimdTestTraits {\n  static int32_t laneCount() {\n    return 1;\n  }\n  static Flt load(const float* data) {\n    return *data;\n  }\n  static void store(Flt v, float* data) {\n    *data = v;\n  }\n  static float lane(Flt v, int32_t /*i*/) {\n    return v;\n  }\n};\n\n// --- x86 SSE ---\n#if defined(__SSE4_1__)\ntemplate <>\nstruct SimdTestTraits<__m128> {\n  static int32_t laneCount() {\n    return 4;\n  }\n  static __m128 load(const float* data) {\n    return _mm_load_ps(data);\n  }\n  static void store(__m128 v, float* data) {\n    _mm_store_ps(data, v);\n  }\n  static float lane(__m128 v, int32_t i) {\n    alignas(16) float buf[4];\n    _mm_store_ps(buf, v);\n    return buf[i];\n  }\n};\n#endif\n\n// --- x86 AVX2 ---\n#if defined(__AVX2__)\ntemplate <>\nstruct SimdTestTraits<__m256> {\n  static int32_t laneCount() {\n    return 8;\n  }\n  static __m256 load(const float* data) {\n    return _mm256_load_ps(data);\n  }\n  static void store(__m256 v, float* data) {\n    _mm256_store_ps(data, v);\n  }\n  static float lane(__m256 v, int32_t i) {\n    alignas(32) float buf[8];\n    _mm256_store_ps(buf, v);\n    return buf[i];\n  }\n};\n#endif\n\n// --- x86 AVX-512 ---\n#if defined(__AVX512F__)\ntemplate <>\nstruct SimdTestTraits<__m512> {\n  static int32_t laneCount() {\n    return 16;\n  }\n  static __m512 load(const float* data) {\n    return _mm512_load_ps(data);\n  }\n  static void store(__m512 v, float* data) {\n    _mm512_store_ps(data, v);\n  }\n  static float lane(__m512 v, int32_t i) {\n    alignas(64) float buf[16];\n    _mm512_store_ps(buf, v);\n    return buf[i];\n  }\n};\n#endif\n\n// --- ARM NEON ---\n#if defined(__aarch64__)\ntemplate <>\nstruct SimdTestTraits<float32x4_t> {\n  static int32_t laneCount() {\n    return 4;\n  }\n  static float32x4_t load(const float* data) {\n    return vld1q_f32(data);\n  }\n  static void store(float32x4_t v, float* data) {\n    vst1q_f32(data, v);\n  }\n  static float lane(float32x4_t v, int32_t i) {\n    float buf[4];\n    vst1q_f32(buf, v);\n    return buf[i];\n  }\n};\n#endif\n\n// --- Highway ---\n#if __has_include(\"hwy/highway.h\")\ntemplate <>\nstruct SimdTestTraits<HwyFloat> {\n  static int32_t laneCount() {\n    return static_cast<int32_t>(hwy::HWY_NAMESPACE::Lanes(HwyFloatTag{}));\n  }\n  static HwyFloat load(const float* data) {\n    return hwy::HWY_NAMESPACE::Load(HwyFloatTag{}, data);\n  }\n  static void store(HwyFloat v, float* data) {\n    hwy::HWY_NAMESPACE::Store(v.v, HwyFloatTag{}, data);\n  }\n  static float lane(HwyFloat v, int32_t i) {\n    return hwy::HWY_NAMESPACE::ExtractLane(v.v, static_cast<size_t>(i));\n  }\n};\n#endif\n\n// ---------------------------------------------------------------------------\n// evalAccuracy<Flt>() — unified accuracy evaluator for scalar and SIMD.\n// ---------------------------------------------------------------------------\n\n// Iterates every representable float in [lo, hi] via detail::nextafter.\n// For SIMD types, packs N consecutive floats per call — processes the full\n// domain in 1/N the iterations of scalar. Returns max ULP error observed.\n//\n// Ground truth `gt` is always called with scalar float.\n// Approximation `fn` is called with Flt (float or SIMD vector).\ntemplate <typename Flt, typename GT, typename FN>\nuint32_t evalAccuracy(GT gt, FN fn, float lo, float hi) {\n  using Traits = SimdTestTraits<Flt>;\n  const int32_t N = Traits::laneCount();\n  uint32_t maxUlp = 0;\n\n  if constexpr (std::is_same_v<Flt, float>) {\n    // Scalar path — matches existing evalAccuracy in eval.h exactly.\n    for (float f = lo; f <= hi; f = detail::nextafter(f)) {\n      float expected = gt(f);\n      float actual = fn(f);\n      uint32_t d = float_distance(expected, actual);\n      maxUlp = std::max(maxUlp, d);\n      if (d > 100) {\n        printf(\"%d, f(%.9g): %.9g, %.9g\\n\", d, f, expected, actual);\n      }\n    }\n  } else {\n    // SIMD path — pack N floats, call fn, compare per-lane.\n    alignas(64) float inputs[kMaxSimdLanes];\n    alignas(64) float outputs[kMaxSimdLanes];\n    float f = lo;\n\n    while (f <= hi) {\n      // Fill input lanes.\n      for (int32_t i = 0; i < N; ++i) {\n        inputs[i] = f;\n        if (f <= hi) {\n          f = detail::nextafter(f);\n        }\n      }\n\n      Flt result = fn(Traits::load(inputs));\n      Traits::store(result, outputs);\n\n      // Compare each lane against ground truth.\n      for (int32_t i = 0; i < N; ++i) {\n        float expected = gt(inputs[i]);\n        float actual = outputs[i];\n        // Skip non-finite results (NaN/Inf comparisons are meaningless).\n        if (!std::isfinite(expected) || !std::isfinite(actual)) {\n          continue;\n        }\n        uint32_t d = float_distance(expected, actual);\n        maxUlp = std::max(maxUlp, d);\n        if (d > 100) {\n          printf(\"%d, f(%.9g): %.9g, %.9g\\n\", d, inputs[i], expected, actual);\n        }\n      }\n    }\n  }\n\n  return maxUlp;\n}\n\n// ---------------------------------------------------------------------------\n// checkLaneByLane<Flt>() — verify specific inputs against ground truth.\n// ---------------------------------------------------------------------------\n\n// Packs `numInputs` floats into SIMD vectors and verifies each output lane\n// against `gt`. For float, just checks one value at a time.\n// numInputs does not need to be a multiple of the lane count; excess inputs\n// are checked in additional calls.\ntemplate <typename Flt, typename GT, typename FN>\nvoid checkLaneByLane(GT gt, FN fn, const float* inputs, int32_t numInputs, uint32_t maxUlps) {\n  using Traits = SimdTestTraits<Flt>;\n  const int32_t N = Traits::laneCount();\n\n  alignas(64) float buf[kMaxSimdLanes];\n  alignas(64) float out[kMaxSimdLanes];\n\n  for (int32_t base = 0; base < numInputs; base += N) {\n    // Fill — pad with last valid input if numInputs isn't a multiple of N.\n    int32_t count = std::min(N, numInputs - base);\n    for (int32_t i = 0; i < count; ++i) {\n      buf[i] = inputs[base + i];\n    }\n    for (int32_t i = count; i < N; ++i) {\n      buf[i] = buf[count - 1];\n    }\n\n    Flt result = fn(Traits::load(buf));\n    Traits::store(result, out);\n\n    for (int32_t i = 0; i < count; ++i) {\n      float expected = gt(buf[i]);\n      float actual = out[i];\n      if (std::isnan(expected)) {\n        EXPECT_TRUE(std::isnan(actual)) << \"input=\" << buf[i] << \" expected NaN, got \" << actual;\n      } else if (std::isinf(expected)) {\n        EXPECT_EQ(expected, actual)\n            << \"input=\" << buf[i] << \" expected=\" << expected << \" actual=\" << actual;\n      } else {\n        uint32_t dist = float_distance(expected, actual);\n        EXPECT_LE(dist, maxUlps) << \"input=\" << buf[i] << \" expected=\" << expected\n                                 << \" actual=\" << actual << \" ulps=\" << dist;\n      }\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// FAST_MATH_ACCURACY_TESTS — generate scalar + all SIMD backend tests.\n// ---------------------------------------------------------------------------\n\n// Usage:\n//   FAST_MATH_ACCURACY_TESTS(Sin, gt_sin, dfm::sin, -128*kPi, 128*kPi, 1)\n//\n// Expands to one TEST per available backend:\n//   TEST(Sin, Scalar)        — evalAccuracy<float>\n//   TEST(SinSse, Range)      — evalAccuracy<__m128>\n//   TEST(SinAvx, Range)      — evalAccuracy<__m256>\n//   TEST(SinAvx512, Range)   — evalAccuracy<__m512>\n//   TEST(SinNeon, Range)     — evalAccuracy<float32x4_t>\n//   TEST(SinHwy, Range)      — evalAccuracy<HwyFloat>\n//\n// For traits variants, define a wrapper template:\n//   template <typename Flt>\n//   Flt sin_max(Flt x) { return dfm::sin<Flt, dfm::MaxAccuracyTraits>(x); }\n//   FAST_MATH_ACCURACY_TESTS(SinMax, gt_sin, sin_max, ...)\n\n// Per-backend macros: expand to a TEST or to nothing based on ISA availability.\n\n#if defined(__SSE4_1__)\n#define FAST_MATH_SSE_TEST(Suite, gt, func, lo, hi, maxUlps)                                     \\\n  TEST(Suite##Sse, Range) {                                                                      \\\n    EXPECT_LE((evalAccuracy<__m128>(gt, func<__m128>, lo, hi)), static_cast<uint32_t>(maxUlps)); \\\n  }\n#else\n#define FAST_MATH_SSE_TEST(Suite, gt, func, lo, hi, maxUlps)\n#endif\n\n#if defined(__AVX2__)\n#define FAST_MATH_AVX_TEST(Suite, gt, func, lo, hi, maxUlps)                                     \\\n  TEST(Suite##Avx, Range) {                                                                      \\\n    EXPECT_LE((evalAccuracy<__m256>(gt, func<__m256>, lo, hi)), static_cast<uint32_t>(maxUlps)); \\\n  }\n#else\n#define FAST_MATH_AVX_TEST(Suite, gt, func, lo, hi, maxUlps)\n#endif\n\n#if defined(__AVX512F__)\n#define FAST_MATH_AVX512_TEST(Suite, gt, func, lo, hi, maxUlps)                                  \\\n  TEST(Suite##Avx512, Range) {                                                                   \\\n    EXPECT_LE((evalAccuracy<__m512>(gt, func<__m512>, lo, hi)), static_cast<uint32_t>(maxUlps)); \\\n  }\n#else\n#define FAST_MATH_AVX512_TEST(Suite, gt, func, lo, hi, maxUlps)\n#endif\n\n#if defined(__aarch64__)\n#define FAST_MATH_NEON_TEST(Suite, gt, func, lo, hi, maxUlps)       \\\n  TEST(Suite##Neon, Range) {                                        \\\n    EXPECT_LE(                                                      \\\n        (evalAccuracy<float32x4_t>(gt, func<float32x4_t>, lo, hi)), \\\n        static_cast<uint32_t>(maxUlps));                            \\\n  }\n#else\n#define FAST_MATH_NEON_TEST(Suite, gt, func, lo, hi, maxUlps)\n#endif\n\n#if __has_include(\"hwy/highway.h\")\n#define FAST_MATH_HWY_TEST(Suite, gt, func, lo, hi, maxUlps)   \\\n  TEST(Suite##Hwy, Range) {                                    \\\n    EXPECT_LE(                                                 \\\n        (evalAccuracy<dispenso::fast_math::HwyFloat>(          \\\n            gt, func<dispenso::fast_math::HwyFloat>, lo, hi)), \\\n        static_cast<uint32_t>(maxUlps));                       \\\n  }\n#else\n#define FAST_MATH_HWY_TEST(Suite, gt, func, lo, hi, maxUlps)\n#endif\n\n// Main macro: generates one test per available backend.\n#define FAST_MATH_ACCURACY_TESTS(Suite, gt, func, lo, hi, maxUlps)                             \\\n  TEST(Suite, Scalar) {                                                                        \\\n    EXPECT_LE((evalAccuracy<float>(gt, func<float>, lo, hi)), static_cast<uint32_t>(maxUlps)); \\\n  }                                                                                            \\\n  FAST_MATH_SSE_TEST(Suite, gt, func, lo, hi, maxUlps)                                         \\\n  FAST_MATH_AVX_TEST(Suite, gt, func, lo, hi, maxUlps)                                         \\\n  FAST_MATH_AVX512_TEST(Suite, gt, func, lo, hi, maxUlps)                                      \\\n  FAST_MATH_NEON_TEST(Suite, gt, func, lo, hi, maxUlps)                                        \\\n  FAST_MATH_HWY_TEST(Suite, gt, func, lo, hi, maxUlps)\n\n// ---------------------------------------------------------------------------\n// FAST_MATH_SPECIAL_TESTS — test hand-picked special values across backends.\n// ---------------------------------------------------------------------------\n//\n// Usage:\n//   static const float kAtanSpecials[] = {0.0f, -1e7f, 1e7f, NaN, Inf, -Inf};\n//   FAST_MATH_SPECIAL_TESTS(AtanSpecial, ::atanf, dfm::atan, kAtanSpecials, 0)\n//\n// Uses checkLaneByLane to verify each output lane against scalar ground truth.\n// NaN inputs are checked for NaN output; finite inputs are checked within maxUlps.\n\n#if defined(__SSE4_1__)\n#define FAST_MATH_SSE_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite##Sse, SpecialVals) {                                    \\\n    checkLaneByLane<__m128>(                                         \\\n        gt,                                                          \\\n        func<__m128>,                                                \\\n        inputs,                                                      \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])),    \\\n        maxUlps);                                                    \\\n  }\n#else\n#define FAST_MATH_SSE_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n#endif\n\n#if defined(__AVX2__)\n#define FAST_MATH_AVX_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite##Avx, SpecialVals) {                                    \\\n    checkLaneByLane<__m256>(                                         \\\n        gt,                                                          \\\n        func<__m256>,                                                \\\n        inputs,                                                      \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])),    \\\n        maxUlps);                                                    \\\n  }\n#else\n#define FAST_MATH_AVX_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n#endif\n\n#if defined(__AVX512F__)\n#define FAST_MATH_AVX512_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite##Avx512, SpecialVals) {                                    \\\n    checkLaneByLane<__m512>(                                            \\\n        gt,                                                             \\\n        func<__m512>,                                                   \\\n        inputs,                                                         \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])),       \\\n        maxUlps);                                                       \\\n  }\n#else\n#define FAST_MATH_AVX512_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n#endif\n\n#if defined(__aarch64__)\n#define FAST_MATH_NEON_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite##Neon, SpecialVals) {                                    \\\n    checkLaneByLane<float32x4_t>(                                     \\\n        gt,                                                           \\\n        func<float32x4_t>,                                            \\\n        inputs,                                                       \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])),     \\\n        maxUlps);                                                     \\\n  }\n#else\n#define FAST_MATH_NEON_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n#endif\n\n#if __has_include(\"hwy/highway.h\")\n#define FAST_MATH_HWY_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite##Hwy, SpecialVals) {                                    \\\n    checkLaneByLane<dispenso::fast_math::HwyFloat>(                  \\\n        gt,                                                          \\\n        func<dispenso::fast_math::HwyFloat>,                         \\\n        inputs,                                                      \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])),    \\\n        maxUlps);                                                    \\\n  }\n#else\n#define FAST_MATH_HWY_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n#endif\n\n// Main macro: generates one special-values test per available backend.\n#define FAST_MATH_SPECIAL_TESTS(Suite, gt, func, inputs, maxUlps) \\\n  TEST(Suite, SpecialScalar) {                                    \\\n    checkLaneByLane<float>(                                       \\\n        gt,                                                       \\\n        func<float>,                                              \\\n        inputs,                                                   \\\n        static_cast<int32_t>(sizeof(inputs) / sizeof(inputs[0])), \\\n        maxUlps);                                                 \\\n  }                                                               \\\n  FAST_MATH_SSE_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)    \\\n  FAST_MATH_AVX_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)    \\\n  FAST_MATH_AVX512_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps) \\\n  FAST_MATH_NEON_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)   \\\n  FAST_MATH_HWY_SPECIAL_TEST(Suite, gt, func, inputs, maxUlps)\n\n// ---------------------------------------------------------------------------\n// Two-argument functions: checkLaneByLane2 + FAST_MATH_SPECIAL_TESTS_2ARG\n// ---------------------------------------------------------------------------\n//\n// For functions like atan2(y,x), hypot(x,y), pow(base,exp) that take two\n// float arguments. Both aInputs and bInputs arrays must have the same length.\n// Parameters are named a/b (not x/y) because the mapping varies by function:\n// atan2 passes (y, x), hypot passes (x, y), pow passes (base, exp).\n//\n// Usage:\n//   static const float kAtan2Y[] = {0.0f, 1.0f, -1.0f, ...};\n//   static const float kAtan2X[] = {1.0f, 0.0f,  1.0f, ...};\n//   FAST_MATH_SPECIAL_TESTS_2ARG(Atan2Special, ::atan2f, dfm::atan2,\n//                                 kAtan2Y, kAtan2X, 3)\n\n// Packs numInputs pairs of (a[i], b[i]) into SIMD vectors and verifies\n// each output lane against gt(a[i], b[i]).\ntemplate <typename Flt, typename GT, typename FN>\nvoid checkLaneByLane2(\n    GT gt,\n    FN fn,\n    const float* aInputs,\n    const float* bInputs,\n    int32_t numInputs,\n    uint32_t maxUlps) {\n  using Traits = SimdTestTraits<Flt>;\n  const int32_t N = Traits::laneCount();\n\n  alignas(64) float aBuf[kMaxSimdLanes];\n  alignas(64) float bBuf[kMaxSimdLanes];\n  alignas(64) float out[kMaxSimdLanes];\n\n  for (int32_t base = 0; base < numInputs; base += N) {\n    int32_t count = std::min(N, numInputs - base);\n    for (int32_t i = 0; i < count; ++i) {\n      aBuf[i] = aInputs[base + i];\n      bBuf[i] = bInputs[base + i];\n    }\n    for (int32_t i = count; i < N; ++i) {\n      aBuf[i] = aBuf[count - 1];\n      bBuf[i] = bBuf[count - 1];\n    }\n\n    Flt result = fn(Traits::load(aBuf), Traits::load(bBuf));\n    Traits::store(result, out);\n\n    for (int32_t i = 0; i < count; ++i) {\n      float expected = gt(aBuf[i], bBuf[i]);\n      float actual = out[i];\n      if (std::isnan(expected)) {\n        EXPECT_TRUE(std::isnan(actual))\n            << \"inputs=(\" << aBuf[i] << \", \" << bBuf[i] << \") expected NaN, got \" << actual;\n      } else if (std::isinf(expected)) {\n        EXPECT_EQ(expected, actual) << \"inputs=(\" << aBuf[i] << \", \" << bBuf[i]\n                                    << \") expected=\" << expected << \" actual=\" << actual;\n      } else {\n        uint32_t dist = float_distance(expected, actual);\n        EXPECT_LE(dist, maxUlps) << \"inputs=(\" << aBuf[i] << \", \" << bBuf[i]\n                                 << \") expected=\" << expected << \" actual=\" << actual\n                                 << \" ulps=\" << dist;\n      }\n    }\n  }\n}\n\n// Per-backend macros for two-argument special tests.\n\n#if defined(__SSE4_1__)\n#define FAST_MATH_SSE_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                       \\\n  TEST(Suite##Sse, SpecialVals) {                                                                 \\\n    checkLaneByLane2<__m128>(                                                                     \\\n        gt, func<__m128>, aIn, bIn, static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])), maxUlps); \\\n  }\n#else\n#define FAST_MATH_SSE_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n#endif\n\n#if defined(__AVX2__)\n#define FAST_MATH_AVX_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                       \\\n  TEST(Suite##Avx, SpecialVals) {                                                                 \\\n    checkLaneByLane2<__m256>(                                                                     \\\n        gt, func<__m256>, aIn, bIn, static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])), maxUlps); \\\n  }\n#else\n#define FAST_MATH_AVX_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n#endif\n\n#if defined(__AVX512F__)\n#define FAST_MATH_AVX512_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                    \\\n  TEST(Suite##Avx512, SpecialVals) {                                                              \\\n    checkLaneByLane2<__m512>(                                                                     \\\n        gt, func<__m512>, aIn, bIn, static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])), maxUlps); \\\n  }\n#else\n#define FAST_MATH_AVX512_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n#endif\n\n#if defined(__aarch64__)\n#define FAST_MATH_NEON_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps) \\\n  TEST(Suite##Neon, SpecialVals) {                                           \\\n    checkLaneByLane2<float32x4_t>(                                           \\\n        gt,                                                                  \\\n        func<float32x4_t>,                                                   \\\n        aIn,                                                                 \\\n        bIn,                                                                 \\\n        static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])),                  \\\n        maxUlps);                                                            \\\n  }\n#else\n#define FAST_MATH_NEON_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n#endif\n\n#if __has_include(\"hwy/highway.h\")\n#define FAST_MATH_HWY_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps) \\\n  TEST(Suite##Hwy, SpecialVals) {                                           \\\n    checkLaneByLane2<dispenso::fast_math::HwyFloat>(                        \\\n        gt,                                                                 \\\n        func<dispenso::fast_math::HwyFloat>,                                \\\n        aIn,                                                                \\\n        bIn,                                                                \\\n        static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])),                 \\\n        maxUlps);                                                           \\\n  }\n#else\n#define FAST_MATH_HWY_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n#endif\n\n// Main macro: generates one two-arg special-values test per available backend.\n#define FAST_MATH_SPECIAL_TESTS_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                         \\\n  TEST(Suite, SpecialScalar) {                                                                   \\\n    checkLaneByLane2<float>(                                                                     \\\n        gt, func<float>, aIn, bIn, static_cast<int32_t>(sizeof(aIn) / sizeof(aIn[0])), maxUlps); \\\n  }                                                                                              \\\n  FAST_MATH_SSE_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                            \\\n  FAST_MATH_AVX_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                            \\\n  FAST_MATH_AVX512_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                         \\\n  FAST_MATH_NEON_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)                           \\\n  FAST_MATH_HWY_SPECIAL_TEST_2ARG(Suite, gt, func, aIn, bIn, maxUlps)\n\n} // namespace testing\n} // namespace fast_math\n} // namespace dispenso\n"
  },
  {
    "path": "tests/fast_math/sin_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nauto sin_accurate = dispenso::fast_math::sin<float, dispenso::fast_math::MaxAccuracyTraits>;\n// MacOS seems to have a slightly busted sin and sinf, but sinl seems to agree with other platforms.\n#if defined(__APPLE__)\nfloat gt_sin(float x) {\n  return ::sinl(x);\n}\n#else\nauto gt_sin = ::sinf;\n#endif //__APPLE__\n\nTEST(Sin, SpecialValues) {\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n  auto sin = dispenso::fast_math::sin<float, dispenso::fast_math::MaxAccuracyTraits>;\n\n  EXPECT_NE(sin(-kInf), sin(-kInf));\n  EXPECT_NE(sin(kInf), sin(kInf));\n  EXPECT_NE(sin(kNaN), sin(kNaN));\n  EXPECT_EQ(sin(0.0f), 0.0f);\n}\n\nconstexpr uint32_t kSinAccurateUlps = 1;\nconstexpr uint32_t kSinAccurateUlpsVeryLarge = 2;\n\nconstexpr uint32_t kSinUlps = 1;\nconstexpr uint32_t kSinUlpsLarge = 2;\n\nTEST(Sin, RangePi) {\n  auto result = dispenso::fast_math::evalAccuracy(gt_sin, sin_accurate, -kPi, kPi);\n\n  EXPECT_LE(result, kSinAccurateUlps);\n}\n\nTEST(Sin, Range128Pi) {\n  auto result = dispenso::fast_math::evalAccuracy(gt_sin, sin_accurate, -128 * kPi, 128 * kPi);\n\n  EXPECT_LE(result, kSinAccurateUlps);\n}\n\nTEST(Sin, Range1MPi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_sin, sin_accurate, -(1 << 20) * kPi, -128 * kPi);\n  EXPECT_LE(result, kSinAccurateUlpsVeryLarge);\n  result = dispenso::fast_math::evalAccuracy(gt_sin, sin_accurate, 128 * kPi, (1 << 20) * kPi);\n\n  EXPECT_LE(result, kSinAccurateUlpsVeryLarge);\n}\n\nTEST(SinLessAccurate, RangePi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_sin, dispenso::fast_math::sin<float>, -kPi, kPi);\n\n  EXPECT_LE(result, kSinUlps);\n}\n\nTEST(SinLessAccurate, Range128Pi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(gt_sin, dispenso::fast_math::sin<float>, -128 * kPi, -kPi);\n\n  EXPECT_LE(result, kSinUlps);\n\n  result =\n      dispenso::fast_math::evalAccuracy(gt_sin, dispenso::fast_math::sin<float>, kPi, 128 * kPi);\n\n  EXPECT_LE(result, kSinUlps);\n}\n\nTEST(SinLessAccurate, Range32768Pi) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      gt_sin, dispenso::fast_math::sin<float>, -32768 * kPi, -128 * kPi);\n\n  EXPECT_LE(result, kSinUlpsLarge);\n\n  result = dispenso::fast_math::evalAccuracy(\n      gt_sin, dispenso::fast_math::sin<float>, 128 * kPi, 32768 * kPi);\n\n  EXPECT_LE(result, kSinUlpsLarge);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt sin_max(Flt x) {\n  return dfm::sin<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(SinDefaultAll, gt_sin, dfm::sin, -32768 * kPi, 32768 * kPi, kSinUlpsLarge)\nFAST_MATH_ACCURACY_TESTS(\n    SinMaxAccAll,\n    gt_sin,\n    sin_max,\n    -(1 << 20) * kPi,\n    (1 << 20) * kPi,\n    kSinAccurateUlpsVeryLarge)\n\n// Special values tested across all SIMD backends.\nstatic const float kSinSpecials[] = {\n    0.0f,\n    -0.0f,\n    kPi,\n    -kPi,\n    kPi_2,\n    -kPi_2,\n    2.0f * kPi,\n    -2.0f * kPi,\n    100.0f,\n    -100.0f,\n    1000.0f,\n    -1000.0f,\n    1e-6f,\n    std::numeric_limits<float>::denorm_min(),\n    std::numeric_limits<float>::min(),\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(SinMaxAccSpecial, gt_sin, sin_max, kSinSpecials, kSinAccurateUlpsVeryLarge)\nFAST_MATH_SPECIAL_TESTS(SinDefaultSpecial, gt_sin, dfm::sin, kSinSpecials, kSinUlpsLarge)\n"
  },
  {
    "path": "tests/fast_math/sincos_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"eval.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\n\nTEST(SinCos, BasicValues) {\n  float s, c;\n  dfm::sincos(0.0f, &s, &c);\n  EXPECT_FLOAT_EQ(s, 0.0f);\n  EXPECT_FLOAT_EQ(c, 1.0f);\n\n  dfm::sincos(kPi_2, &s, &c);\n  EXPECT_NEAR(s, 1.0f, 1e-6f);\n  EXPECT_NEAR(c, 0.0f, 1e-6f);\n\n  dfm::sincos(kPi, &s, &c);\n  EXPECT_NEAR(s, 0.0f, 1e-6f);\n  EXPECT_NEAR(c, -1.0f, 1e-6f);\n\n  dfm::sincos(-kPi_2, &s, &c);\n  EXPECT_NEAR(s, -1.0f, 1e-6f);\n  EXPECT_NEAR(c, 0.0f, 1e-6f);\n}\n\nTEST(SinCos, MatchesSeparateCalls) {\n  constexpr int kSteps = 1024;\n  constexpr float kRange = 128.0f * kPi;\n  constexpr float kDelta = 2.0f * kRange / kSteps;\n\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -kRange + static_cast<float>(i) * kDelta;\n    float s, c;\n    dfm::sincos(x, &s, &c);\n    float expected_s = dfm::sin(x);\n    float expected_c = dfm::cos(x);\n    EXPECT_EQ(s, expected_s) << \"sin mismatch at x=\" << x;\n    EXPECT_EQ(c, expected_c) << \"cos mismatch at x=\" << x;\n  }\n}\n\nTEST(SinCos, AccuracyVsLibc) {\n  constexpr int kSteps = 4096;\n  constexpr float kRange = 128.0f * kPi;\n  constexpr float kDelta = 2.0f * kRange / kSteps;\n\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -kRange + static_cast<float>(i) * kDelta;\n    float s, c;\n    dfm::sincos(x, &s, &c);\n\n    float gt_s = static_cast<float>(::sin(static_cast<double>(x)));\n    float gt_c = static_cast<float>(::cos(static_cast<double>(x)));\n\n    uint32_t sin_dist = dfm::float_distance(gt_s, s);\n    uint32_t cos_dist = dfm::float_distance(gt_c, c);\n\n    EXPECT_LE(sin_dist, 2u) << \"sin at x=\" << x << \" expected=\" << gt_s << \" actual=\" << s;\n    EXPECT_LE(cos_dist, 2u) << \"cos at x=\" << x << \" expected=\" << gt_c << \" actual=\" << c;\n  }\n}\n\nTEST(SinCos, MaxAccuracy) {\n  constexpr int kSteps = 4096;\n  constexpr float kRange = 128.0f * kPi;\n  constexpr float kDelta = 2.0f * kRange / kSteps;\n\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -kRange + static_cast<float>(i) * kDelta;\n    float s, c;\n    dfm::sincos<float, dfm::MaxAccuracyTraits>(x, &s, &c);\n\n    float gt_s = static_cast<float>(::sin(static_cast<double>(x)));\n    float gt_c = static_cast<float>(::cos(static_cast<double>(x)));\n\n    EXPECT_LE(dfm::float_distance(gt_s, s), 2u) << \"sin at x=\" << x;\n    EXPECT_LE(dfm::float_distance(gt_c, c), 2u) << \"cos at x=\" << x;\n  }\n}\n"
  },
  {
    "path": "tests/fast_math/sinpi_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"eval.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\n\n// Ground truth for sinpi/cospi: use double-precision sinpi where available,\n// otherwise compute via exact range reduction in double + sin/cos.\nstatic float gt_sinpi(float x) {\n  double xd = static_cast<double>(x);\n  // Exact range reduction in double: much more precise than sin(pi * x).\n  double j = std::round(2.0 * xd);\n  double r = xd - j * 0.5;\n  double t = r * M_PI;\n  int qi = static_cast<int>(j) & 3;\n  double sv = std::sin(t);\n  double cv = std::cos(t);\n  double result;\n  switch (qi) {\n    case 0:\n      result = sv;\n      break;\n    case 1:\n      result = cv;\n      break;\n    case 2:\n      result = -sv;\n      break;\n    case 3:\n      result = -cv;\n      break;\n    default:\n      result = 0.0;\n      break;\n  }\n  return static_cast<float>(result);\n}\n\nstatic float gt_cospi(float x) {\n  double xd = static_cast<double>(x);\n  double j = std::round(2.0 * xd);\n  double r = xd - j * 0.5;\n  double t = r * M_PI;\n  int qi = (static_cast<int>(j) + 1) & 3;\n  double sv = std::sin(t);\n  double cv = std::cos(t);\n  double result;\n  switch (qi) {\n    case 0:\n      result = sv;\n      break;\n    case 1:\n      result = cv;\n      break;\n    case 2:\n      result = -sv;\n      break;\n    case 3:\n      result = -cv;\n      break;\n    default:\n      result = 0.0;\n      break;\n  }\n  return static_cast<float>(result);\n}\n\n// --- sinpi ---\n\nTEST(SinPi, ExactValues) {\n  // sinpi(n) = 0 for all integers\n  EXPECT_EQ(dfm::sinpi(0.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(1.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(-1.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(2.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(100.0f), 0.0f);\n\n  // sinpi(0.5) = 1, sinpi(-0.5) = -1\n  EXPECT_FLOAT_EQ(dfm::sinpi(0.5f), 1.0f);\n  EXPECT_FLOAT_EQ(dfm::sinpi(-0.5f), -1.0f);\n  EXPECT_FLOAT_EQ(dfm::sinpi(1.5f), -1.0f);\n  EXPECT_FLOAT_EQ(dfm::sinpi(-1.5f), 1.0f);\n}\n\nTEST(SinPi, AccuracyVsLibc) {\n  constexpr int kSteps = 4096;\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -10.0f + 20.0f * static_cast<float>(i) / kSteps;\n    float result = dfm::sinpi(x);\n    float expected = gt_sinpi(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 2u) << \"sinpi(\" << x << \") = \" << result << \" expected \" << expected;\n  }\n}\n\n// --- cospi ---\n\nTEST(CosPi, ExactValues) {\n  // cospi(n) = ±1 for integers\n  EXPECT_FLOAT_EQ(dfm::cospi(0.0f), 1.0f);\n  EXPECT_FLOAT_EQ(dfm::cospi(1.0f), -1.0f);\n  EXPECT_FLOAT_EQ(dfm::cospi(-1.0f), -1.0f);\n  EXPECT_FLOAT_EQ(dfm::cospi(2.0f), 1.0f);\n\n  // cospi(0.5) = 0\n  EXPECT_NEAR(dfm::cospi(0.5f), 0.0f, 1e-6f);\n  EXPECT_NEAR(dfm::cospi(-0.5f), 0.0f, 1e-6f);\n  EXPECT_NEAR(dfm::cospi(1.5f), 0.0f, 1e-6f);\n}\n\nTEST(CosPi, AccuracyVsLibc) {\n  constexpr int kSteps = 4096;\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -10.0f + 20.0f * static_cast<float>(i) / kSteps;\n    float result = dfm::cospi(x);\n    float expected = gt_cospi(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 2u) << \"cospi(\" << x << \") = \" << result << \" expected \" << expected;\n  }\n}\n\n// --- sincospi ---\n\nTEST(SinCosPi, MatchesSeparateCalls) {\n  constexpr int kSteps = 1024;\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -10.0f + 20.0f * static_cast<float>(i) / kSteps;\n    float s, c;\n    dfm::sincospi(x, &s, &c);\n    EXPECT_EQ(s, dfm::sinpi(x)) << \"sin mismatch at x=\" << x;\n    EXPECT_EQ(c, dfm::cospi(x)) << \"cos mismatch at x=\" << x;\n  }\n}\n\nTEST(SinCosPi, AccuracyVsLibc) {\n  constexpr int kSteps = 4096;\n  for (int i = 0; i < kSteps; ++i) {\n    float x = -10.0f + 20.0f * static_cast<float>(i) / kSteps;\n    float s, c;\n    dfm::sincospi(x, &s, &c);\n    float gt_s = gt_sinpi(x);\n    float gt_c = gt_cospi(x);\n    EXPECT_LE(dfm::float_distance(gt_s, s), 2u) << \"sinpi at x=\" << x;\n    EXPECT_LE(dfm::float_distance(gt_c, c), 2u) << \"cospi at x=\" << x;\n  }\n}\n\nTEST(SinPi, LargeArguments) {\n  // For |x| >= 2^23, every float is an integer, sinpi = 0.\n  EXPECT_EQ(dfm::sinpi(8388608.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(16777216.0f), 0.0f);\n  EXPECT_EQ(dfm::sinpi(-8388608.0f), 0.0f);\n}\n\nTEST(CosPi, LargeArguments) {\n  // For |x| >= 2^23, every float is an integer, cospi = ±1.\n  float c = dfm::cospi(8388608.0f);\n  EXPECT_TRUE(c == 1.0f || c == -1.0f);\n  c = dfm::cospi(16777216.0f);\n  EXPECT_TRUE(c == 1.0f || c == -1.0f);\n}\n"
  },
  {
    "path": "tests/fast_math/sse_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include <gtest/gtest.h>\n\n#if defined(__SSE4_1__)\n\nnamespace dfm = dispenso::fast_math;\nusing SseFloat = dfm::SseFloat;\nusing SseInt32 = dfm::SseInt32;\nusing SseUint32 = dfm::SseUint32;\n\n// Helper: extract lane i from __m128.\nstatic float lane(__m128 v, int i) {\n  alignas(16) float buf[4];\n  _mm_store_ps(buf, v);\n  return buf[i];\n}\n\n// Helper: extract lane i from __m128i (as int32_t).\nstatic int32_t lane(__m128i v, int i) {\n  alignas(16) int32_t buf[4];\n  _mm_store_si128(reinterpret_cast<__m128i*>(buf), v);\n  return buf[i];\n}\n\n// Helper: create __m128 from 4 distinct values.\nstatic __m128 make4(float a, float b, float c, float d) {\n  return _mm_set_ps(d, c, b, a);\n}\n\n// ---- SseFloat basic arithmetic ----\n\nTEST(SseFloat, Broadcast) {\n  SseFloat v(3.0f);\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_EQ(lane(v, i), 3.0f);\n  }\n}\n\nTEST(SseFloat, Arithmetic) {\n  SseFloat a = make4(1.0f, 2.0f, 3.0f, 4.0f);\n  SseFloat b = make4(5.0f, 6.0f, 7.0f, 8.0f);\n\n  SseFloat sum = a + b;\n  EXPECT_EQ(lane(sum, 0), 6.0f);\n  EXPECT_EQ(lane(sum, 3), 12.0f);\n\n  SseFloat diff = b - a;\n  EXPECT_EQ(lane(diff, 0), 4.0f);\n  EXPECT_EQ(lane(diff, 3), 4.0f);\n\n  SseFloat prod = a * b;\n  EXPECT_EQ(lane(prod, 0), 5.0f);\n  EXPECT_EQ(lane(prod, 3), 32.0f);\n\n  SseFloat quot = b / a;\n  EXPECT_EQ(lane(quot, 0), 5.0f);\n  EXPECT_EQ(lane(quot, 1), 3.0f);\n}\n\nTEST(SseFloat, Negation) {\n  SseFloat a = make4(1.0f, -2.0f, 0.0f, 3.0f);\n  SseFloat neg = -a;\n  EXPECT_EQ(lane(neg, 0), -1.0f);\n  EXPECT_EQ(lane(neg, 1), 2.0f);\n  EXPECT_EQ(lane(neg, 2), -0.0f);\n  EXPECT_EQ(lane(neg, 3), -3.0f);\n}\n\n// ---- SseFloat comparisons ----\n\nTEST(SseFloat, Comparisons) {\n  SseFloat a = make4(1.0f, 2.0f, 3.0f, 4.0f);\n  SseFloat b = make4(2.0f, 2.0f, 1.0f, 5.0f);\n\n  SseFloat lt = a < b;\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, 0)), 0u); // 1 < 2 true\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 1)), 0u); // 2 < 2 false\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(lane(lt, 2)), 0u); // 3 < 1 false\n  EXPECT_NE(dfm::bit_cast<uint32_t>(lane(lt, 3)), 0u); // 4 < 5 true\n}\n\n// ---- SseInt32 arithmetic ----\n\nTEST(SseInt32, BasicOps) {\n  SseInt32 a(10);\n  SseInt32 b(3);\n  EXPECT_EQ(lane(a + b, 0), 13);\n  EXPECT_EQ(lane(a - b, 0), 7);\n  EXPECT_EQ(lane(a * b, 0), 30);\n}\n\nTEST(SseInt32, ShiftOps) {\n  SseInt32 a(8);\n  EXPECT_EQ(lane(a << 2, 0), 32);\n  EXPECT_EQ(lane(a >> 1, 0), 4);\n\n  SseInt32 neg(-8);\n  EXPECT_EQ(lane(neg >> 1, 0), -4); // Arithmetic shift preserves sign\n}\n\n// ---- SseUint32 ----\n\nTEST(SseUint32, LogicalShift) {\n  SseUint32 a(0x80000000u);\n  // Logical shift right — does NOT preserve sign.\n  EXPECT_EQ(static_cast<uint32_t>(lane(a >> 1, 0)), 0x40000000u);\n}\n\n// ---- bit_cast ----\n\nTEST(SseBitCast, FloatToInt) {\n  SseFloat f(1.0f);\n  SseInt32 i = dfm::bit_cast<SseInt32>(f);\n  EXPECT_EQ(lane(i, 0), 0x3f800000);\n}\n\nTEST(SseBitCast, IntToFloat) {\n  SseInt32 i(0x40000000);\n  SseFloat f = dfm::bit_cast<SseFloat>(i);\n  EXPECT_EQ(lane(f, 0), 2.0f);\n}\n\nTEST(SseBitCast, RoundTrip) {\n  SseFloat original = make4(1.0f, -2.0f, 0.5f, 42.0f);\n  SseFloat roundtripped = dfm::bit_cast<SseFloat>(dfm::bit_cast<SseInt32>(original));\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_EQ(lane(roundtripped, i), lane(original, i));\n  }\n}\n\n// ---- FloatTraits<SseFloat> ----\n\nTEST(SseFloatTraits, Conditional) {\n  SseFloat mask = SseFloat(make4(1.0f, 0.0f, 1.0f, 0.0f)) > SseFloat(0.5f);\n  SseFloat x(10.0f);\n  SseFloat y(20.0f);\n  SseFloat result = dfm::FloatTraits<SseFloat>::conditional(mask, x, y);\n  EXPECT_EQ(lane(result, 0), 10.0f);\n  EXPECT_EQ(lane(result, 1), 20.0f);\n  EXPECT_EQ(lane(result, 2), 10.0f);\n  EXPECT_EQ(lane(result, 3), 20.0f);\n}\n\nTEST(SseFloatTraits, Fma) {\n  SseFloat a(2.0f), b(3.0f), c(4.0f);\n  SseFloat result = dfm::FloatTraits<SseFloat>::fma(a, b, c);\n  EXPECT_EQ(lane(result, 0), 10.0f);\n}\n\nTEST(SseFloatTraits, MinMax) {\n  SseFloat a = make4(1.0f, 5.0f, 3.0f, 7.0f);\n  SseFloat b = make4(4.0f, 2.0f, 6.0f, 0.0f);\n  SseFloat mn = dfm::FloatTraits<SseFloat>::min(a, b);\n  SseFloat mx = dfm::FloatTraits<SseFloat>::max(a, b);\n  EXPECT_EQ(lane(mn, 0), 1.0f);\n  EXPECT_EQ(lane(mn, 1), 2.0f);\n  EXPECT_EQ(lane(mx, 0), 4.0f);\n  EXPECT_EQ(lane(mx, 1), 5.0f);\n}\n\n// ---- Util functions ----\n\nTEST(SseUtil, FloorSmall) {\n  __m128 x = make4(1.5f, -1.5f, 2.0f, 0.1f);\n  __m128 result = dfm::floor_small(x);\n  EXPECT_EQ(lane(result, 0), 1.0f);\n  EXPECT_EQ(lane(result, 1), -2.0f);\n  EXPECT_EQ(lane(result, 2), 2.0f);\n  EXPECT_EQ(lane(result, 3), 0.0f);\n}\n\nTEST(SseUtil, ConvertToInt) {\n  __m128 x = make4(1.6f, -1.6f, 2.5f, 0.4f);\n  __m128i result = dfm::convert_to_int(x);\n  EXPECT_EQ(lane(result, 0), 2); // Round to nearest even\n  EXPECT_EQ(lane(result, 1), -2);\n  EXPECT_EQ(lane(result, 2), 2); // Round to nearest even: 2.5 → 2\n  EXPECT_EQ(lane(result, 3), 0);\n}\n\nTEST(SseUtil, Gather) {\n  float table[] = {10.0f, 20.0f, 30.0f, 40.0f, 50.0f};\n  __m128i indices = _mm_set_epi32(4, 2, 0, 1);\n  __m128 result = dfm::gather<SseFloat>(table, indices);\n  EXPECT_EQ(lane(result, 0), 20.0f);\n  EXPECT_EQ(lane(result, 1), 10.0f);\n  EXPECT_EQ(lane(result, 2), 30.0f);\n  EXPECT_EQ(lane(result, 3), 50.0f);\n}\n\nTEST(SseUtil, IntDivBy3) {\n  __m128i a = _mm_set_epi32(30, 9, 6, 3);\n  __m128i result = dfm::int_div_by_3(a);\n  EXPECT_EQ(lane(result, 0), 1);\n  EXPECT_EQ(lane(result, 1), 2);\n  EXPECT_EQ(lane(result, 2), 3);\n  EXPECT_EQ(lane(result, 3), 10);\n}\n\nTEST(SseUtil, Signof) {\n  __m128 x = make4(1.0f, -1.0f, 0.0f, -0.0f);\n  __m128 result = dfm::signof(x);\n  EXPECT_EQ(lane(result, 0), 1.0f);\n  EXPECT_EQ(lane(result, 1), -1.0f);\n  EXPECT_EQ(lane(result, 2), 1.0f);\n  EXPECT_EQ(lane(result, 3), -1.0f);\n}\n\nTEST(SseUtil, Signofi) {\n  __m128i a = _mm_set_epi32(-5, 0, 10, -1);\n  __m128i result = dfm::signofi<SseFloat>(SseInt32(a));\n  EXPECT_EQ(lane(result, 0), -1);\n  EXPECT_EQ(lane(result, 1), 1);\n  EXPECT_EQ(lane(result, 2), 1);\n  EXPECT_EQ(lane(result, 3), -1);\n}\n\n#else // !defined(__SSE4_1__)\n\n// Dummy test so the binary has at least one test on non-SSE platforms.\nTEST(SseFloat, NotAvailable) {\n  GTEST_SKIP() << \"SSE4.1 not available\";\n}\n\n#endif // defined(__SSE4_1__)\n"
  },
  {
    "path": "tests/fast_math/tan_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nTEST(Tan, SpecialValues) {\n  constexpr float kInf = std::numeric_limits<float>::infinity();\n  constexpr auto kNaN = std::numeric_limits<float>::quiet_NaN();\n\n  EXPECT_NE(dispenso::fast_math::tan(-kInf), dispenso::fast_math::tan(-kInf));\n  EXPECT_NE(dispenso::fast_math::tan(kInf), dispenso::fast_math::tan(kInf));\n  EXPECT_NE(dispenso::fast_math::tan(kNaN), dispenso::fast_math::tan(kNaN));\n  EXPECT_EQ(dispenso::fast_math::tan(0.0f), 0.0f);\n}\n\nconstexpr uint32_t kTanAccurateUlps = 3;\nconstexpr uint32_t kTanAccurateUlpsLg = 4;\n\nTEST(TanLessAccurate, Range8Pi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(::tanf, dispenso::fast_math::tan<float>, -8 * kPi, 8 * kPi);\n\n  EXPECT_LE(result, kTanAccurateUlps);\n}\n\nTEST(TanLessAccurate, Range1KPi) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      ::tanf, dispenso::fast_math::tan<float>, -(1 << 10) * kPi, -8 * kPi);\n  EXPECT_LE(result, kTanAccurateUlps);\n\n  result = dispenso::fast_math::evalAccuracy(\n      ::tanf, dispenso::fast_math::tan<float>, 8 * kPi, (1 << 10) * kPi);\n  EXPECT_LE(result, kTanAccurateUlps);\n}\n\nTEST(TanLessAccurate, Range32KPi) {\n  auto result = dispenso::fast_math::evalAccuracy(\n      ::tanf, dispenso::fast_math::tan<float>, -(1 << 15) * kPi, -(1 << 10) * kPi);\n  EXPECT_LE(result, kTanAccurateUlps);\n\n  result = dispenso::fast_math::evalAccuracy(\n      ::tanf, dispenso::fast_math::tan<float>, (1 << 10) * kPi, (1 << 15) * kPi);\n  EXPECT_LE(result, kTanAccurateUlps);\n}\n\nauto tan_accurate = dispenso::fast_math::tan<float, dispenso::fast_math::MaxAccuracyTraits>;\n\nTEST(TanAccurate, Range2MPi) {\n  auto result =\n      dispenso::fast_math::evalAccuracy(::tanf, tan_accurate, -(1 << 20) * kPi, -(1 << 15) * kPi);\n  EXPECT_LE(result, kTanAccurateUlpsLg);\n\n  result =\n      dispenso::fast_math::evalAccuracy(::tanf, tan_accurate, (1 << 15) * kPi, (1 << 20) * kPi);\n  EXPECT_LE(result, kTanAccurateUlpsLg);\n}\n\n// Wrapper for MaxAccuracyTraits — macro instantiates func<Flt>.\ntemplate <typename Flt>\nFlt tan_max(Flt x) {\n  return dfm::tan<Flt, dfm::MaxAccuracyTraits>(x);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nFAST_MATH_ACCURACY_TESTS(\n    TanDefaultAll,\n    ::tanf,\n    dfm::tan,\n    -(1 << 15) * kPi,\n    (1 << 15) * kPi,\n    kTanAccurateUlps)\nFAST_MATH_ACCURACY_TESTS(\n    TanMaxAccAll,\n    ::tanf,\n    tan_max,\n    -(1 << 20) * kPi,\n    (1 << 20) * kPi,\n    kTanAccurateUlpsLg)\n\n// Special values tested across all SIMD backends.\nstatic const float kTanSpecials[] = {\n    0.0f,\n    -0.0f,\n    kPi_4,\n    -kPi_4,\n    1.0f,\n    -1.0f,\n    50.0f,\n    -50.0f,\n    200.0f,\n    -200.0f,\n    std::numeric_limits<float>::quiet_NaN(),\n    std::numeric_limits<float>::infinity(),\n    -std::numeric_limits<float>::infinity()};\nFAST_MATH_SPECIAL_TESTS(TanDefaultSpecial, ::tanf, dfm::tan, kTanSpecials, kTanAccurateUlps)\nFAST_MATH_SPECIAL_TESTS(TanMaxAccSpecial, ::tanf, tan_max, kTanSpecials, kTanAccurateUlpsLg)\n"
  },
  {
    "path": "tests/fast_math/tanh_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/fast_math.h>\n\n#include \"simd_test_utils.h\"\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\nusing namespace dispenso::fast_math::testing;\n\nstatic float gt_tanh(float x) {\n  return static_cast<float>(std::tanh(static_cast<double>(x)));\n}\n\nTEST(Tanh, SpecialValues) {\n  EXPECT_EQ(dfm::tanh(0.0f), 0.0f);\n  EXPECT_FLOAT_EQ(dfm::tanh(1.0f), gt_tanh(1.0f));\n  EXPECT_FLOAT_EQ(dfm::tanh(-1.0f), gt_tanh(-1.0f));\n}\n\nTEST(Tanh, Saturation) {\n  // For |x| >= ~9, tanh rounds to ±1 in float.\n  EXPECT_EQ(dfm::tanh(10.0f), 1.0f);\n  EXPECT_EQ(dfm::tanh(-10.0f), -1.0f);\n  EXPECT_EQ(dfm::tanh(100.0f), 1.0f);\n  EXPECT_EQ(dfm::tanh(-100.0f), -1.0f);\n}\n\nTEST(Tanh, NearZero) {\n  // tanh(x) ≈ x for small x. Verify no cancellation.\n  float xs[] = {1e-7f, -1e-7f, 1e-5f, -1e-5f, 1e-3f, -1e-3f, 0.01f, -0.01f, 0.1f, -0.1f};\n  for (float x : xs) {\n    float expected = gt_tanh(x);\n    float result = dfm::tanh(x);\n    uint32_t dist = dfm::float_distance(expected, result);\n    EXPECT_LE(dist, 2u) << \"tanh(\" << x << \"): expected=\" << expected << \" got=\" << result;\n  }\n}\n\nTEST(Tanh, RangeSmall) {\n  uint32_t ulps = dfm::evalAccuracy(gt_tanh, dfm::tanh<float>, -1.0f, 1.0f);\n  EXPECT_LE(ulps, 2u);\n}\n\nTEST(Tanh, RangeFull) {\n  uint32_t ulps = dfm::evalAccuracy(gt_tanh, dfm::tanh<float>, -10.0f, 10.0f);\n  EXPECT_LE(ulps, 2u);\n}\n\n// Unified accuracy tests — scalar + all SIMD backends, same threshold.\nconstexpr uint32_t kTanhMaxUlps = 2;\nFAST_MATH_ACCURACY_TESTS(TanhAll, gt_tanh, dfm::tanh, -10.0f, 10.0f, kTanhMaxUlps)\n\n// Special values tested across all SIMD backends.\n// tanh SIMD doesn't propagate NaN — only test in-domain values + saturation.\nstatic const float kTanhSpecials[] = {\n    0.0f,\n    -0.0f,\n    0.5f,\n    -0.5f,\n    1.0f,\n    -1.0f,\n    5.0f,\n    -5.0f,\n    10.0f,\n    -10.0f,\n    100.0f,\n    -100.0f,\n    0.01f,\n    -0.01f,\n    1e-7f,\n    -1e-7f};\nFAST_MATH_SPECIAL_TESTS(TanhSpecial, gt_tanh, dfm::tanh, kTanhSpecials, kTanhMaxUlps)\n"
  },
  {
    "path": "tests/fast_math/test_main.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Rosetta detection for fast_math SIMD tests.\n// When running under Rosetta (x86 emulation on ARM Mac), Cody-Waite range\n// reduction accuracy breaks because FMA is emulated as separate multiply+add.\n// This file registers a GoogleTest environment that disables all tests when\n// Rosetta is detected.\n\n#if defined(__APPLE__) && defined(__x86_64__)\n#include <sys/sysctl.h>\n#include <cstdio>\n\n#include <gtest/gtest.h>\n\nstatic bool isRosetta() {\n  int ret = 0;\n  size_t size = sizeof(ret);\n  return sysctlbyname(\"sysctl.proc_translated\", &ret, &size, nullptr, 0) == 0 && ret == 1;\n}\n\nclass RosettaGuard : public testing::Environment {\n public:\n  void SetUp() override {\n    if (isRosetta()) {\n      printf(\"Rosetta detected: skipping fast_math SIMD tests.\\n\");\n      printf(\"FMA emulation breaks Cody-Waite range reduction accuracy.\\n\");\n      printf(\"Run on native ARM or native x86 hardware.\\n\");\n      // Set filter to match no tests, effectively skipping all.\n      testing::GTEST_FLAG(filter) = \"DISABLED_RosettaSkip\";\n    }\n  }\n};\n\n// Register before main() runs via global constructor.\nstatic auto* rosetta_env [[maybe_unused]] = testing::AddGlobalTestEnvironment(new RosettaGuard());\n#endif // __APPLE__ && __x86_64__\n"
  },
  {
    "path": "tests/fast_math/ulp_eval.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// Exhaustive ULP evaluation tool for single-argument fast_math functions.\n// Uses dispenso::parallel_for for fast evaluation across concentric bands.\n// Tests both +x and -x for each representable float in each band.\n//\n// Usage: buck run <target>\n// To add a new function, add an entry to the `funcs` vector in main().\n\n#include <atomic>\n#include <cmath>\n#include <cstdint>\n#include <cstdio>\n\n#include <dispenso/parallel_for.h>\n\n#include <dispenso/fast_math/fast_math.h>\n#include <dispenso/fast_math/util.h>\n\nnamespace dfm = dispenso::fast_math;\n\nstruct Band {\n  float lo, hi;\n  const char* label;\n};\n\nstatic constexpr float kPi = 3.14159265358979323846f;\n\n// Bands for periodic functions (sin, cos, tan).\nstatic Band kTrigBands[] = {\n    {0.0f, kPi / 2, \"0 to pi/2\"},\n    {kPi / 2, kPi, \"pi/2 to pi\"},\n    {kPi, 2 * kPi, \"pi to 2pi\"},\n    {2 * kPi, 4 * kPi, \"2pi to 4pi\"},\n    {4 * kPi, 8 * kPi, \"4pi to 8pi\"},\n    {16 * kPi, 32 * kPi, \"16pi to 32pi\"},\n    {64 * kPi, 128 * kPi, \"64pi to 128pi\"},\n    {512 * kPi, 1024 * kPi, \"512pi to 1024pi\"},\n    {65536 * kPi, 131072 * kPi, \"65536pi to 131072pi\"},\n    {524288 * kPi, 1048576 * kPi, \"524288pi to 1Mpi\"},\n};\n\n// Bands for [0, FLT_MAX] functions (exp, log, cbrt, sqrt).\nstatic Band kPositiveBands[] = {\n    {0.0f, 1.0f, \"0 to 1\"},\n    {1.0f, 10.0f, \"1 to 10\"},\n    {10.0f, 100.0f, \"10 to 100\"},\n    {100.0f, 1000.0f, \"100 to 1000\"},\n    {1000.0f, 1e6f, \"1e3 to 1e6\"},\n    {1e6f, 1e10f, \"1e6 to 1e10\"},\n    {1e10f, 1e20f, \"1e10 to 1e20\"},\n    {1e20f, 1e30f, \"1e20 to 1e30\"},\n    {1e30f, 1e38f, \"1e30 to 1e38\"},\n};\n\n// Bands for [-1, 1] functions (asin, acos).\nstatic Band kUnitBands[] = {\n    {0.0f, 0.25f, \"0 to 0.25\"},\n    {0.25f, 0.5f, \"0.25 to 0.5\"},\n    {0.5f, 0.75f, \"0.5 to 0.75\"},\n    {0.75f, 1.0f, \"0.75 to 1.0\"},\n};\n\n// Bands for [0, FLT_MAX] functions (atan).\nstatic Band kAtanBands[] = {\n    {0.0f, 0.5f, \"0 to 0.5\"},\n    {0.5f, 1.0f, \"0.5 to 1\"},\n    {1.0f, 2.0f, \"1 to 2\"},\n    {2.0f, 10.0f, \"2 to 10\"},\n    {10.0f, 100.0f, \"10 to 100\"},\n    {100.0f, 1e6f, \"100 to 1e6\"},\n    {1e6f, 1e20f, \"1e6 to 1e20\"},\n    {1e20f, 1e38f, \"1e20 to 1e38\"},\n};\n\nusing FnType = float (*)(float);\n\nstatic void evalBands(const char* name, FnType gt, FnType fn, Band* bands, int32_t numBands) {\n  printf(\"%-20s  %5s  %8s  %-s\\n\", name, \"ULP\", \">=3ULP\", \"Worst input\");\n  for (int32_t bi = 0; bi < numBands; ++bi) {\n    const auto& b = bands[bi];\n    uint32_t lo_bits = dfm::bit_cast<uint32_t>(b.lo);\n    uint32_t hi_bits = dfm::bit_cast<uint32_t>(b.hi);\n    uint32_t count = hi_bits - lo_bits + 1;\n\n    std::atomic<uint32_t> maxUlp{0};\n    std::atomic<float> worstX{0.0f};\n    std::atomic<uint32_t> count3{0};\n\n    dispenso::parallel_for(\n        dispenso::makeChunkedRange(0u, count, 64u * 1024u), [&](uint32_t begin, uint32_t end) {\n          uint32_t localMax = 0;\n          float localWorst = 0.0f;\n          uint32_t localCount3 = 0;\n          for (uint32_t idx = begin; idx < end; ++idx) {\n            uint32_t bits = lo_bits + idx;\n            float f = dfm::bit_cast<float>(bits);\n            for (float x : {f, -f}) {\n              float g = gt(x);\n              float a = fn(x);\n              // Skip non-finite results: NaN/inf comparisons via float_distance\n              // produce garbage. Functions with asymmetric domains (log1p) may\n              // produce NaN for mirrored inputs — this is expected, not an error.\n              if (!std::isfinite(g) || !std::isfinite(a))\n                continue;\n              uint32_t d = dfm::float_distance(g, a);\n              if (d >= 3)\n                localCount3++;\n              if (d > localMax) {\n                localMax = d;\n                localWorst = x;\n              }\n            }\n          }\n          count3.fetch_add(localCount3, std::memory_order_relaxed);\n          uint32_t prev = maxUlp.load(std::memory_order_relaxed);\n          while (localMax > prev) {\n            if (maxUlp.compare_exchange_weak(prev, localMax, std::memory_order_relaxed)) {\n              worstX.store(localWorst, std::memory_order_relaxed);\n              break;\n            }\n          }\n        });\n\n    printf(\"  %-18s  %5u  %8u  x=%.9g\\n\", b.label, maxUlp.load(), count3.load(), worstX.load());\n  }\n}\n\ntemplate <int32_t N>\nstatic void eval(const char* name, FnType gt, FnType fn, Band (&bands)[N]) {\n  evalBands(name, gt, fn, bands, N);\n}\n\n// Ground truth wrappers — use long double on macOS for better reference accuracy.\nstatic float gt_sin(float x) {\n#if defined(__APPLE__)\n  return static_cast<float>(::sinl(x));\n#else\n  return ::sinf(x);\n#endif\n}\nstatic float gt_cos(float x) {\n#if defined(__APPLE__)\n  return static_cast<float>(::cosl(x));\n#else\n  return ::cosf(x);\n#endif\n}\nstatic float gt_tan(float x) {\n  return static_cast<float>(::tanl(x));\n}\nstatic float gt_asin(float x) {\n  return ::asinf(x);\n}\nstatic float gt_acos(float x) {\n  return ::acosf(x);\n}\nstatic float gt_atan(float x) {\n  return ::atanf(x);\n}\nstatic float gt_exp(float x) {\n  return ::expf(x);\n}\nstatic float gt_exp2(float x) {\n  return ::exp2f(x);\n}\nstatic float gt_log(float x) {\n  return ::logf(x);\n}\nstatic float gt_log2(float x) {\n  return ::log2f(x);\n}\nstatic float gt_log10(float x) {\n  return ::log10f(x);\n}\nstatic float gt_cbrt(float x) {\n  return ::cbrtf(x);\n}\nstatic float gt_expm1(float x) {\n  return static_cast<float>(std::expm1(static_cast<double>(x)));\n}\nstatic float gt_log1p(float x) {\n  return static_cast<float>(std::log1p(static_cast<double>(x)));\n}\nstatic float gt_tanh(float x) {\n  return static_cast<float>(std::tanh(static_cast<double>(x)));\n}\nstatic float gt_erf(float x) {\n  return static_cast<float>(std::erf(static_cast<double>(x)));\n}\n\n// Bands for exp functions — [-89, 89] covers the non-overflow range.\nstatic Band kExpBands[] = {\n    {0.0f, 1.0f, \"0 to 1\"},\n    {1.0f, 10.0f, \"1 to 10\"},\n    {10.0f, 40.0f, \"10 to 40\"},\n    {40.0f, 89.0f, \"40 to 89\"},\n};\n\n// Bands for expm1 — near-zero focus, plus full exp range.\n// The mirrored negative side is also valid (expm1(-89) = -1).\nstatic Band kExpm1Bands[] = {\n    {0.0f, 0.001f, \"0 to 0.001\"},\n    {0.001f, 0.1f, \"0.001 to 0.1\"},\n    {0.1f, 1.0f, \"0.1 to 1\"},\n    {1.0f, 10.0f, \"1 to 10\"},\n    {10.0f, 89.0f, \"10 to 89\"},\n};\n\n// Bands for log1p — covers [0, 1e38] and mirrors to [-1e38, 0].\n// For x < -1, log1p is undefined and both gt/fn return NaN, which the\n// eval loop skips. So mirroring large bands is safe.\nstatic Band kLog1pBands[] = {\n    {0.0f, 0.001f, \"0 to 0.001\"},\n    {0.001f, 0.1f, \"0.001 to 0.1\"},\n    {0.1f, 1.0f, \"0.1 to 1\"},\n    {1.0f, 100.0f, \"1 to 100\"},\n    {100.0f, 1e10f, \"100 to 1e10\"},\n    {1e10f, 1e30f, \"1e10 to 1e30\"},\n    {1e30f, 1e38f, \"1e30 to 1e38\"},\n};\n\n// Bands for tanh — saturates to ±1 at ~±9.\nstatic Band kTanhBands[] = {\n    {0.0f, 0.001f, \"0 to 0.001\"},\n    {0.001f, 0.1f, \"0.001 to 0.1\"},\n    {0.1f, 1.0f, \"0.1 to 1\"},\n    {1.0f, 5.0f, \"1 to 5\"},\n    {5.0f, 10.0f, \"5 to 10\"},\n};\n\nstatic Band kErfBands[] = {\n    {0.0f, 0.001f, \"0 to 0.001\"},\n    {0.001f, 0.1f, \"0.001 to 0.1\"},\n    {0.1f, 0.5f, \"0.1 to 0.5\"},\n    {0.5f, 1.0f, \"0.5 to 1\"},\n    {1.0f, 2.0f, \"1 to 2\"},\n    {2.0f, 3.0f, \"2 to 3\"},\n    {3.0f, 3.92f, \"3 to 3.92\"},\n};\n\nint main() {\n  printf(\"=== Trigonometric ===\\n\");\n  eval(\"sin\", gt_sin, dfm::sin<float>, kTrigBands);\n  printf(\"\\n\");\n  eval(\"cos\", gt_cos, dfm::cos<float>, kTrigBands);\n  printf(\"\\n\");\n  eval(\"tan\", gt_tan, dfm::tan<float>, kTrigBands);\n\n  printf(\"\\n=== Inverse Trig ===\\n\");\n  eval(\"asin\", gt_asin, dfm::asin<float>, kUnitBands);\n  printf(\"\\n\");\n  eval(\"acos\", gt_acos, dfm::acos<float>, kUnitBands);\n  printf(\"\\n\");\n  eval(\"atan\", gt_atan, dfm::atan<float>, kAtanBands);\n\n  printf(\"\\n=== Exponential ===\\n\");\n  eval(\"exp\", gt_exp, dfm::exp<float>, kExpBands);\n  printf(\"\\n\");\n  eval(\"exp2\", gt_exp2, dfm::exp2<float>, kExpBands);\n\n  printf(\"\\n=== Logarithmic ===\\n\");\n  eval(\"log\", gt_log, dfm::log<float>, kPositiveBands);\n  printf(\"\\n\");\n  eval(\"log2\", gt_log2, dfm::log2<float>, kPositiveBands);\n  printf(\"\\n\");\n  eval(\"log10\", gt_log10, dfm::log10<float>, kPositiveBands);\n\n  printf(\"\\n=== Other ===\\n\");\n  eval(\"cbrt\", gt_cbrt, dfm::cbrt<float>, kPositiveBands);\n\n  printf(\"\\n=== Precision-near-zero ===\\n\");\n  eval(\"expm1\", gt_expm1, dfm::expm1<float>, kExpm1Bands);\n  printf(\"\\n\");\n  eval(\"log1p\", gt_log1p, dfm::log1p<float>, kLog1pBands);\n  printf(\"\\n\");\n  eval(\"tanh\", gt_tanh, dfm::tanh<float>, kTanhBands);\n  printf(\"\\n\");\n  eval(\"erf\", gt_erf, dfm::erf<float>, kErfBands);\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/fast_math/util_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/fast_math/util.h>\n\n#include <cmath>\n#include <limits>\n\n#include <gtest/gtest.h>\n\nnamespace dfm = dispenso::fast_math;\n\n// ---- bit_cast ----\n\nTEST(BitCast, FloatToUint) {\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(0.0f), 0u);\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(-0.0f), 0x80000000u);\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(1.0f), 0x3f800000u);\n  EXPECT_EQ(dfm::bit_cast<uint32_t>(-1.0f), 0xbf800000u);\n}\n\nTEST(BitCast, UintToFloat) {\n  EXPECT_EQ(dfm::bit_cast<float>(0x3f800000u), 1.0f);\n  EXPECT_EQ(dfm::bit_cast<float>(0x40000000u), 2.0f);\n}\n\nTEST(BitCast, RoundTrip) {\n  float vals[] = {0.0f, 1.0f, -1.0f, 3.14f, -2.718f, std::numeric_limits<float>::infinity()};\n  for (float v : vals) {\n    EXPECT_EQ(dfm::bit_cast<float>(dfm::bit_cast<uint32_t>(v)), v);\n    EXPECT_EQ(dfm::bit_cast<float>(dfm::bit_cast<int32_t>(v)), v);\n  }\n}\n\n// ---- float_distance ----\n\nTEST(FloatDistance, IdenticalValues) {\n  EXPECT_EQ(dfm::float_distance(1.0f, 1.0f), 0u);\n  EXPECT_EQ(dfm::float_distance(0.0f, 0.0f), 0u);\n  EXPECT_EQ(dfm::float_distance(-1.0f, -1.0f), 0u);\n}\n\nTEST(FloatDistance, OneUlp) {\n  float a = 1.0f;\n  float b = std::nextafter(a, 2.0f);\n  EXPECT_EQ(dfm::float_distance(a, b), 1u);\n  EXPECT_EQ(dfm::float_distance(b, a), 1u);\n}\n\nTEST(FloatDistance, SymmetricForPositive) {\n  float a = 1.0f;\n  float b = 1.5f;\n  EXPECT_EQ(dfm::float_distance(a, b), dfm::float_distance(b, a));\n}\n\nTEST(FloatDistance, DenormalsAreZero) {\n  // Denormals should be treated as zero\n  float denorm = std::numeric_limits<float>::denorm_min();\n  EXPECT_EQ(dfm::float_distance(denorm, 0.0f), 0u);\n}\n\n// ---- signof ----\n\nTEST(Signof, PositiveValues) {\n  EXPECT_EQ(dfm::signof(1.0f), 1.0f);\n  EXPECT_EQ(dfm::signof(42.0f), 1.0f);\n  EXPECT_EQ(dfm::signof(0.001f), 1.0f);\n}\n\nTEST(Signof, NegativeValues) {\n  EXPECT_EQ(dfm::signof(-1.0f), -1.0f);\n  EXPECT_EQ(dfm::signof(-42.0f), -1.0f);\n  EXPECT_EQ(dfm::signof(-0.001f), -1.0f);\n}\n\nTEST(Signof, Zero) {\n  // +0 should give +1, -0 should give -1\n  EXPECT_EQ(dfm::signof(0.0f), 1.0f);\n  EXPECT_EQ(dfm::signof(-0.0f), -1.0f);\n}\n\n// ---- signofi ----\n\nTEST(Signofi, PositiveValues) {\n  EXPECT_EQ((dfm::signofi<float>(1)), 1);\n  EXPECT_EQ((dfm::signofi<float>(100)), 1);\n}\n\nTEST(Signofi, NegativeValues) {\n  EXPECT_EQ((dfm::signofi<float>(-1)), -1);\n  EXPECT_EQ((dfm::signofi<float>(-100)), -1);\n}\n\nTEST(Signofi, Zero) {\n  EXPECT_EQ((dfm::signofi<float>(0)), 1);\n}\n\n// ---- nonnormal ----\n\nTEST(Nonnormal, IntVersion) {\n  // Inf: exponent all 1s, mantissa 0\n  int32_t inf_bits = dfm::bit_cast<int32_t>(std::numeric_limits<float>::infinity());\n  EXPECT_TRUE(dfm::nonnormal<float>(inf_bits));\n\n  // NaN: exponent all 1s, mantissa nonzero\n  int32_t nan_bits = dfm::bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN());\n  EXPECT_TRUE(dfm::nonnormal<float>(nan_bits));\n\n  // Normal number\n  int32_t one_bits = dfm::bit_cast<int32_t>(1.0f);\n  EXPECT_FALSE(dfm::nonnormal<float>(one_bits));\n\n  int32_t neg_one_bits = dfm::bit_cast<int32_t>(-1.0f);\n  EXPECT_FALSE(dfm::nonnormal<float>(neg_one_bits));\n}\n\nTEST(Nonnormal, FloatVersion) {\n  EXPECT_TRUE(dfm::nonnormal<float>(std::numeric_limits<float>::infinity()));\n  EXPECT_TRUE(dfm::nonnormal<float>(-std::numeric_limits<float>::infinity()));\n  EXPECT_TRUE(dfm::nonnormal<float>(std::numeric_limits<float>::quiet_NaN()));\n  EXPECT_FALSE(dfm::nonnormal<float>(1.0f));\n  EXPECT_FALSE(dfm::nonnormal<float>(-42.0f));\n}\n\n// ---- nonnormalOrZero ----\n\nTEST(NonnormalOrZero, Normal) {\n  int32_t bits = dfm::bit_cast<int32_t>(1.0f);\n  EXPECT_FALSE(dfm::nonnormalOrZero<float>(bits));\n  bits = dfm::bit_cast<int32_t>(-42.0f);\n  EXPECT_FALSE(dfm::nonnormalOrZero<float>(bits));\n}\n\nTEST(NonnormalOrZero, Zero) {\n  int32_t bits = dfm::bit_cast<int32_t>(0.0f);\n  EXPECT_TRUE(dfm::nonnormalOrZero<float>(bits));\n}\n\nTEST(NonnormalOrZero, Inf) {\n  int32_t bits = dfm::bit_cast<int32_t>(std::numeric_limits<float>::infinity());\n  EXPECT_TRUE(dfm::nonnormalOrZero<float>(bits));\n}\n\nTEST(NonnormalOrZero, NaN) {\n  int32_t bits = dfm::bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN());\n  EXPECT_TRUE(dfm::nonnormalOrZero<float>(bits));\n}\n\n// ---- convert_to_int ----\n\nTEST(ConvertToInt, BasicValues) {\n  EXPECT_EQ(dfm::convert_to_int(0.0f), 0);\n  EXPECT_EQ(dfm::convert_to_int(1.0f), 1);\n  EXPECT_EQ(dfm::convert_to_int(-1.0f), -1);\n  EXPECT_EQ(dfm::convert_to_int(2.0f), 2);\n  EXPECT_EQ(dfm::convert_to_int(-2.0f), -2);\n}\n\nTEST(ConvertToInt, Rounding) {\n  // SSE uses round-to-nearest-even (banker's rounding)\n  EXPECT_EQ(dfm::convert_to_int(1.4f), 1);\n  EXPECT_EQ(dfm::convert_to_int(1.6f), 2);\n  EXPECT_EQ(dfm::convert_to_int(-1.4f), -1);\n  EXPECT_EQ(dfm::convert_to_int(-1.6f), -2);\n  // Banker's rounding: 0.5 rounds to nearest even\n  EXPECT_EQ(dfm::convert_to_int(0.5f), 0); // 0.5 → 0 (even)\n  EXPECT_EQ(dfm::convert_to_int(1.5f), 2); // 1.5 → 2 (even)\n  EXPECT_EQ(dfm::convert_to_int(2.5f), 2); // 2.5 → 2 (even)\n  EXPECT_EQ(dfm::convert_to_int(3.5f), 4); // 3.5 → 4 (even)\n  EXPECT_EQ(dfm::convert_to_int(-0.5f), 0);\n  EXPECT_EQ(dfm::convert_to_int(-1.5f), -2);\n}\n\nTEST(ConvertToInt, LargeValues) {\n  EXPECT_EQ(dfm::convert_to_int(100.0f), 100);\n  EXPECT_EQ(dfm::convert_to_int(-100.0f), -100);\n  EXPECT_EQ(dfm::convert_to_int(1000.0f), 1000);\n}\n\n// ---- convert_to_int_clamped ----\n\nTEST(ConvertToIntClamped, WithinRange) {\n  EXPECT_EQ((dfm::convert_to_int_clamped<float, -10, 10>(5.0f)), 5);\n  EXPECT_EQ((dfm::convert_to_int_clamped<float, -10, 10>(-5.0f)), -5);\n  EXPECT_EQ((dfm::convert_to_int_clamped<float, -10, 10>(0.0f)), 0);\n}\n\nTEST(ConvertToIntClamped, AtBounds) {\n  EXPECT_EQ((dfm::convert_to_int_clamped<float, -10, 10>(10.0f)), 10);\n  EXPECT_EQ((dfm::convert_to_int_clamped<float, -10, 10>(-10.0f)), -10);\n}\n\nTEST(ConvertToIntClamped, ClampedAbove) {\n  EXPECT_LE((dfm::convert_to_int_clamped<float, -10, 10>(100.0f)), 10);\n}\n\nTEST(ConvertToIntClamped, ClampedBelow) {\n  EXPECT_GE((dfm::convert_to_int_clamped<float, -10, 10>(-100.0f)), -10);\n}\n\n// ---- floor_small ----\n\nTEST(FloorSmall, Integers) {\n  EXPECT_EQ(dfm::floor_small(0.0f), 0.0f);\n  EXPECT_EQ(dfm::floor_small(1.0f), 1.0f);\n  EXPECT_EQ(dfm::floor_small(-1.0f), -1.0f);\n  EXPECT_EQ(dfm::floor_small(5.0f), 5.0f);\n}\n\nTEST(FloorSmall, PositiveFractions) {\n  EXPECT_EQ(dfm::floor_small(1.5f), 1.0f);\n  EXPECT_EQ(dfm::floor_small(1.9f), 1.0f);\n  EXPECT_EQ(dfm::floor_small(1.1f), 1.0f);\n  EXPECT_EQ(dfm::floor_small(0.5f), 0.0f);\n}\n\nTEST(FloorSmall, NegativeFractions) {\n  EXPECT_EQ(dfm::floor_small(-0.5f), -1.0f);\n  EXPECT_EQ(dfm::floor_small(-1.5f), -2.0f);\n  EXPECT_EQ(dfm::floor_small(-1.1f), -2.0f);\n  EXPECT_EQ(dfm::floor_small(-0.1f), -1.0f);\n}\n\nTEST(FloorSmall, MatchesStdFloor) {\n  float vals[] = {\n      0.0f,\n      0.1f,\n      0.5f,\n      0.9f,\n      1.0f,\n      1.5f,\n      2.7f,\n      100.3f,\n      -0.1f,\n      -0.5f,\n      -0.9f,\n      -1.0f,\n      -1.5f,\n      -2.7f,\n      -100.3f};\n  for (float v : vals) {\n    EXPECT_EQ(dfm::floor_small(v), std::floor(v)) << \"Mismatch for \" << v;\n  }\n}\n\n// ---- min ----\n\nTEST(Min, BasicValues) {\n  EXPECT_EQ(dfm::min<float>(1.0f, 2.0f), 1.0f);\n  EXPECT_EQ(dfm::min<float>(2.0f, 1.0f), 1.0f);\n  EXPECT_EQ(dfm::min<float>(-1.0f, 1.0f), -1.0f);\n  EXPECT_EQ(dfm::min<float>(5.0f, 5.0f), 5.0f);\n}\n\nTEST(Min, NanBehavior) {\n  // If first arg is NaN and second is not, should return second\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  EXPECT_EQ(dfm::min<float>(nan, 1.0f), 1.0f);\n}\n\n// ---- clamp_allow_nan ----\n\nTEST(ClampAllowNan, WithinRange) {\n  EXPECT_EQ(dfm::clamp_allow_nan<float>(0.5f, 0.0f, 1.0f), 0.5f);\n}\n\nTEST(ClampAllowNan, BelowMin) {\n  EXPECT_EQ(dfm::clamp_allow_nan<float>(-1.0f, 0.0f, 1.0f), 0.0f);\n}\n\nTEST(ClampAllowNan, AboveMax) {\n  EXPECT_EQ(dfm::clamp_allow_nan<float>(2.0f, 0.0f, 1.0f), 1.0f);\n}\n\nTEST(ClampAllowNan, NanInput) {\n  float nan = std::numeric_limits<float>::quiet_NaN();\n  float result = dfm::clamp_allow_nan<float>(nan, 0.0f, 1.0f);\n  // \"allow_nan\" refers to handling NaN in the bounds, not clamping NaN input.\n  // With NaN input on SSE, NaN propagates through min/max chain.\n  EXPECT_TRUE(std::isnan(result));\n}\n\n// ---- clamp_no_nan ----\n\nTEST(ClampNoNan, WithinRange) {\n  EXPECT_EQ(dfm::clamp_no_nan<float>(0.5f, 0.0f, 1.0f), 0.5f);\n}\n\nTEST(ClampNoNan, BelowMin) {\n  EXPECT_EQ(dfm::clamp_no_nan<float>(-1.0f, 0.0f, 1.0f), 0.0f);\n}\n\nTEST(ClampNoNan, AboveMax) {\n  EXPECT_EQ(dfm::clamp_no_nan<float>(2.0f, 0.0f, 1.0f), 1.0f);\n}\n\nTEST(ClampNoNan, AtBounds) {\n  EXPECT_EQ(dfm::clamp_no_nan<float>(0.0f, 0.0f, 1.0f), 0.0f);\n  EXPECT_EQ(dfm::clamp_no_nan<float>(1.0f, 0.0f, 1.0f), 1.0f);\n}\n\n// ---- gather ----\n\nTEST(Gather, BasicLookup) {\n  float table[] = {10.0f, 20.0f, 30.0f, 40.0f, 50.0f};\n  EXPECT_EQ(dfm::gather<float>(table, 0), 10.0f);\n  EXPECT_EQ(dfm::gather<float>(table, 2), 30.0f);\n  EXPECT_EQ(dfm::gather<float>(table, 4), 50.0f);\n}\n\n// ---- nbool_as_one / bool_as_one ----\n\nTEST(NboolAsOne, Float) {\n  EXPECT_EQ((dfm::nbool_as_one<float, bool>(true)), 0.0f);\n  EXPECT_EQ((dfm::nbool_as_one<float, bool>(false)), 1.0f);\n}\n\nTEST(NboolAsOne, Int) {\n  EXPECT_EQ((dfm::nbool_as_one<int32_t, bool>(true)), 0);\n  EXPECT_EQ((dfm::nbool_as_one<int32_t, bool>(false)), 1);\n}\n\nTEST(BoolAsOne, Float) {\n  EXPECT_EQ((dfm::bool_as_one<float, bool>(true)), 1.0f);\n  EXPECT_EQ((dfm::bool_as_one<float, bool>(false)), 0.0f);\n}\n\nTEST(BoolAsOne, Int) {\n  EXPECT_EQ((dfm::bool_as_one<int32_t, bool>(true)), 1);\n  EXPECT_EQ((dfm::bool_as_one<int32_t, bool>(false)), 0);\n}\n\n// ---- bool_as_mask ----\n\nTEST(BoolAsMask, TrueGivesAllOnes) {\n  int32_t mask = dfm::bool_as_mask<int32_t, bool>(true);\n  EXPECT_EQ(mask, static_cast<int32_t>(0xFFFFFFFF));\n}\n\nTEST(BoolAsMask, FalseGivesZero) {\n  int32_t mask = dfm::bool_as_mask<int32_t, bool>(false);\n  EXPECT_EQ(mask, 0);\n}\n\n// ---- bool_apply_or_zero ----\n\nTEST(BoolApplyOrZero, TrueReturnsValue) {\n  EXPECT_EQ((dfm::bool_apply_or_zero<int32_t>(true, 42)), 42);\n  EXPECT_EQ((dfm::bool_apply_or_zero<int32_t>(true, -7)), -7);\n}\n\nTEST(BoolApplyOrZero, FalseReturnsZero) {\n  EXPECT_EQ((dfm::bool_apply_or_zero<int32_t>(false, 42)), 0);\n  EXPECT_EQ((dfm::bool_apply_or_zero<int32_t>(false, -7)), 0);\n}\n\nTEST(BoolApplyOrZero, FloatTrue) {\n  float result = dfm::bool_apply_or_zero<float>(true, 3.14f);\n  EXPECT_EQ(result, 3.14f);\n}\n\nTEST(BoolApplyOrZero, FloatFalse) {\n  float result = dfm::bool_apply_or_zero<float>(false, 3.14f);\n  EXPECT_EQ(result, 0.0f);\n}\n\n// ---- int_div_by_3 ----\n\nTEST(IntDivBy3, ExactMultiples) {\n  EXPECT_EQ(dfm::int_div_by_3(0), 0);\n  EXPECT_EQ(dfm::int_div_by_3(3), 1);\n  EXPECT_EQ(dfm::int_div_by_3(6), 2);\n  EXPECT_EQ(dfm::int_div_by_3(9), 3);\n  EXPECT_EQ(dfm::int_div_by_3(30), 10);\n  EXPECT_EQ(dfm::int_div_by_3(300), 100);\n}\n\nTEST(IntDivBy3, WithRemainder) {\n  // Truncation toward zero like integer division\n  EXPECT_EQ(dfm::int_div_by_3(1), 0);\n  EXPECT_EQ(dfm::int_div_by_3(2), 0);\n  EXPECT_EQ(dfm::int_div_by_3(4), 1);\n  EXPECT_EQ(dfm::int_div_by_3(5), 1);\n  EXPECT_EQ(dfm::int_div_by_3(7), 2);\n  EXPECT_EQ(dfm::int_div_by_3(8), 2);\n  EXPECT_EQ(dfm::int_div_by_3(10), 3);\n}\n\nTEST(IntDivBy3, LargeValues) {\n  // Values used in cbrt magic constant computations\n  for (int32_t i = 0; i < 10000; i += 7) {\n    EXPECT_EQ(dfm::int_div_by_3(i), i / 3) << \"Mismatch at \" << i;\n  }\n}\n"
  },
  {
    "path": "tests/for_each_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <deque>\n#include <list>\n#include <numeric>\n#include <set>\n#include <unordered_map>\n#include <vector>\n\n#include <dispenso/for_each.h>\n\n#include <gtest/gtest.h>\n\n#include \"test_tid.h\"\n\ntemplate <typename Container>\nvoid forEachTestHelper() {\n  constexpr size_t kNumVals = 1 << 15;\n  Container c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace_back(i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each(\n      std::begin(c), std::end(c), [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEach, Vector) {\n  forEachTestHelper<std::vector<size_t>>();\n}\n\nTEST(ForEach, List) {\n  forEachTestHelper<std::list<size_t>>();\n}\n\nTEST(ForEach, Deque) {\n  forEachTestHelper<std::deque<size_t>>();\n}\n\nTEST(ForEach, Set) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::set<size_t> c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace(i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each(\n      std::begin(c), std::end(c), [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEach, UnorderedMap) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::unordered_map<size_t, size_t> c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace(i, i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each(\n      std::begin(c), std::end(c), [&validated](auto p) { validated[p.second] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\ntemplate <typename Container>\nvoid forEachNTestHelper() {\n  constexpr size_t kNumVals = 1 << 15;\n  Container c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace_back(i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each_n(\n      std::begin(c), kNumVals, [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEachN, Vector) {\n  forEachNTestHelper<std::vector<size_t>>();\n}\n\nTEST(ForEachN, List) {\n  forEachNTestHelper<std::list<size_t>>();\n}\n\nTEST(ForEachN, Deque) {\n  forEachNTestHelper<std::deque<size_t>>();\n}\n\nTEST(ForEachN, Set) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::set<size_t> c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace(i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each_n(\n      std::begin(c), kNumVals, [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEachN, UnorderedMap) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::unordered_map<size_t, size_t> c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace(i, i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each_n(\n      std::begin(c), kNumVals, [&validated](auto p) { validated[p.second] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEach, NoWaitFewerThreads) {\n  constexpr size_t kNumVals = 1 << 14;\n  std::atomic<size_t> count(0);\n  std::atomic<bool> canStart(false);\n\n  std::vector<size_t> c;\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace_back(i);\n  }\n\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n\n  dispenso::for_each(\n      tasks,\n      std::begin(c),\n      std::end(c),\n      [&count, &canStart](auto val) {\n        while (!canStart.load(std::memory_order_acquire))\n          ;\n\n        count.fetch_add(val, std::memory_order_release);\n      },\n      {3, false} /* 3 threads, no wait */);\n\n  std::this_thread::sleep_for(std::chrono::milliseconds(20));\n\n  // Use sequential consistency to ensure that this store can't be put before the sleep, nor after\n  // the wait.\n  canStart.store(true, std::memory_order_seq_cst);\n\n  tasks.wait();\n\n  EXPECT_EQ(count.load(std::memory_order_acquire), 134209536);\n}\n\nTEST(ForEachN, NoWaitFewerThreads) {\n  constexpr size_t kNumVals = 1 << 13;\n  std::atomic<size_t> count(0);\n  std::atomic<bool> canStart(false);\n\n  std::vector<size_t> c;\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace_back(i);\n  }\n\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n\n  dispenso::for_each_n(\n      tasks,\n      std::begin(c),\n      kNumVals,\n      [&count, &canStart](auto val) {\n        while (!canStart.load(std::memory_order_acquire))\n          ;\n\n        count.fetch_add(val, std::memory_order_release);\n      },\n      {3, false} /* 3 threads, no wait */);\n\n  std::this_thread::sleep_for(std::chrono::milliseconds(20));\n\n  // Use sequential consistency to ensure that this store can't be put before the sleep, nor after\n  // the wait.\n  canStart.store(true, std::memory_order_seq_cst);\n\n  tasks.wait();\n\n  EXPECT_EQ(count.load(std::memory_order_acquire), 33550336);\n}\n\nTEST(ForEach, SmallSet) {\n  constexpr size_t kNumVals = 3;\n  std::set<size_t> c;\n\n  for (size_t i = 0; i < kNumVals; ++i) {\n    c.emplace(i);\n  }\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  dispenso::for_each(\n      std::begin(c), std::end(c), [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEach, EmptySet) {\n  std::set<int> emptySet;\n  dispenso::for_each(std::begin(emptySet), std::end(emptySet), [](int /*index*/) {\n    EXPECT_FALSE(true) << \"Should not get into this lambda\";\n  });\n}\n\nTEST(ForEach, References) {\n  std::vector<int> values;\n  for (int i = 0; i < 100; ++i) {\n    values.push_back(i);\n  }\n\n  dispenso::for_each(std::begin(values), std::end(values), [](int& i) { i = -i; });\n\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(values[i], -i);\n  }\n}\n\nTEST(ForEach, Cascade) {\n  std::vector<int> values;\n  for (int i = 0; i < 100; ++i) {\n    values.push_back(i);\n  }\n\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ForEachOptions options;\n  options.wait = false;\n\n  dispenso::for_each(\n      taskSet,\n      std::begin(values),\n      std::end(values),\n      [](int& i) {\n        std::this_thread::sleep_for(std::chrono::microseconds(1));\n        i = -i;\n      },\n      options);\n\n  dispenso::ForEachOptions waitOptions;\n  std::set<int> emptySet;\n  dispenso::for_each(\n      taskSet,\n      std::begin(emptySet),\n      std::end(emptySet),\n      [](int /*index*/) { EXPECT_FALSE(true) << \"Should not get into this lambda\"; },\n      waitOptions);\n\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(values[i], -i);\n  }\n}\n\nstatic void testMaxThreads(size_t poolSize, uint32_t maxThreads, bool testWaitOption) {\n  resetTestTid();\n  size_t numAvailableThreads = poolSize + testWaitOption;\n  std::vector<int> threadLocalSums(numAvailableThreads, 0);\n  dispenso::ThreadPool pool(poolSize);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::ForEachOptions options;\n  options.maxThreads = maxThreads;\n  options.wait = testWaitOption;\n\n  constexpr size_t kLen = 9999;\n\n  auto func = [&threadLocalSums](int index) {\n    assert(index > 0); // for correctness of numNonZero\n    std::this_thread::yield();\n    int tid = getTestTid();\n    threadLocalSums[tid] += index;\n  };\n\n  std::vector<int> v(kLen);\n  std::iota(v.begin(), v.end(), 1);\n\n  dispenso::for_each_n(tasks, v.cbegin(), kLen, func, options);\n\n  if (!testWaitOption) {\n    // We didn't tell the parallel_for to wait, so we need to do it here to ensure the loop is\n    // complete.\n    tasks.wait();\n  }\n  int total = 0;\n  int numNonZero = 0;\n\n  for (size_t i = 0; i < numAvailableThreads; ++i) {\n    numNonZero += threadLocalSums[i] > 0;\n    total += threadLocalSums[i];\n  }\n\n  // 0 indicates serial execution per API spec\n  size_t translatedMaxThreads = maxThreads == 0 ? 1 : maxThreads;\n  EXPECT_LE(numNonZero, std::min((size_t)translatedMaxThreads, numAvailableThreads));\n  EXPECT_EQ(total, 49995000);\n}\n\nTEST(ForEach, OptionsMaxThreadsBigPoolBlocking) {\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 4, waitOption);\n}\n\nTEST(ForEach, OptionsMaxThreadsBigPoolNonBlocking) {\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 4, waitOption);\n}\n\nTEST(ForEach, OptionsMaxThreadsSmallPoolBlocking) {\n  constexpr bool waitOption = true;\n  testMaxThreads(4, 8, waitOption);\n}\n\nTEST(ForEach, OptionsMaxThreadsSmallPoolNonBlocking) {\n  constexpr bool waitOption = false;\n  testMaxThreads(4, 8, waitOption);\n}\n\nTEST(ForEach, OptionsMaxThreadsSerialBlocking) {\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 0, waitOption);\n}\n\nTEST(ForEach, OptionsMaxThreadsSerialNonBlocking) {\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 0, waitOption);\n}\n\n// Iterator with no default constructor — exercises the SmallVector<Iter>\n// boundary list which must not require Iter to be default-constructible.\nstruct NoDefaultCtorIterator {\n  using iterator_category = std::input_iterator_tag;\n  using difference_type = std::ptrdiff_t;\n  using value_type = size_t;\n  using pointer = const size_t*;\n  using reference = const size_t&;\n\n  explicit NoDefaultCtorIterator(const std::vector<size_t>& v, size_t idx) : v_(&v), idx_(idx) {}\n\n  reference operator*() const {\n    return (*v_)[idx_];\n  }\n  NoDefaultCtorIterator& operator++() {\n    ++idx_;\n    return *this;\n  }\n  NoDefaultCtorIterator operator++(int) {\n    auto tmp = *this;\n    ++idx_;\n    return tmp;\n  }\n  friend bool operator==(const NoDefaultCtorIterator& a, const NoDefaultCtorIterator& b) {\n    return a.idx_ == b.idx_;\n  }\n  friend bool operator!=(const NoDefaultCtorIterator& a, const NoDefaultCtorIterator& b) {\n    return a.idx_ != b.idx_;\n  }\n\n private:\n  const std::vector<size_t>* v_;\n  size_t idx_;\n};\n\nTEST(ForEach, NonDefaultConstructibleIterator) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::vector<size_t> data(kNumVals);\n  std::iota(data.begin(), data.end(), 0);\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  NoDefaultCtorIterator begin(data, 0);\n  NoDefaultCtorIterator end(data, kNumVals);\n\n  dispenso::for_each(begin, end, [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n\nTEST(ForEachN, NonDefaultConstructibleIterator) {\n  constexpr size_t kNumVals = 1 << 12;\n  std::vector<size_t> data(kNumVals);\n  std::iota(data.begin(), data.end(), 0);\n\n  std::vector<uint8_t> validated(kNumVals, 0);\n\n  NoDefaultCtorIterator begin(data, 0);\n\n  dispenso::for_each_n(begin, kNumVals, [&validated](size_t val) { validated[val] = true; });\n\n  for (auto v : validated) {\n    EXPECT_TRUE(v);\n  }\n}\n"
  },
  {
    "path": "tests/forward_shared_pool.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/thread_pool.h>\n\n#ifdef _WIN32\n__declspec(dllexport)\n#else\n__attribute__((visibility(\"default\")))\n#endif\nvoid* DISPENSO_EXPORT_NAME() {\n  return &dispenso::globalThreadPool();\n}\n"
  },
  {
    "path": "tests/future_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/future.h>\n\n#include <gtest/gtest.h>\n\nTEST(Future, Invalid) {\n  dispenso::Future<void> future;\n  EXPECT_FALSE(future.valid());\n  future = dispenso::make_ready_future();\n  EXPECT_TRUE(future.valid());\n}\n\nTEST(Future, MakeReady) {\n  auto voidFuture = dispenso::make_ready_future();\n  EXPECT_TRUE(voidFuture.is_ready());\n  voidFuture.get();\n\n  int valueA = 66;\n  auto intFuture = dispenso::make_ready_future(valueA);\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_EQ(valueA, intFuture.get());\n\n  auto intRefFuture = dispenso::make_ready_future(std::ref(valueA));\n  EXPECT_TRUE(intRefFuture.is_ready());\n  EXPECT_EQ(valueA, intRefFuture.get());\n  --valueA;\n  EXPECT_EQ(valueA, intRefFuture.get());\n\n  EXPECT_EQ(&valueA, &intRefFuture.get());\n}\n\nTEST(Future, ThreadPool) {\n  int foo = 10;\n  dispenso::Future<void> voidFuture([&foo]() { foo = 7; }, dispenso::globalThreadPool());\n  EXPECT_TRUE(voidFuture.valid());\n  voidFuture.get();\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture([]() { return 33; }, dispenso::globalThreadPool());\n  EXPECT_TRUE(intFuture.valid());\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture(\n      [&refTo]() -> int& { return refTo; }, dispenso::globalThreadPool());\n  EXPECT_TRUE(refFuture.valid());\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, ThreadPoolForceQueuing) {\n  int foo = 10;\n  dispenso::Future<void> voidFuture(\n      [&foo]() { foo = 7; }, dispenso::globalThreadPool(), std::launch::async);\n  EXPECT_TRUE(voidFuture.valid());\n  voidFuture.get();\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture(\n      []() { return 33; }, dispenso::globalThreadPool(), std::launch::async);\n  EXPECT_TRUE(intFuture.valid());\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture(\n      [&refTo]() -> int& { return refTo; }, dispenso::globalThreadPool(), std::launch::async);\n  EXPECT_TRUE(refFuture.valid());\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, TaskSet) {\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n  int foo = 10;\n  dispenso::Future<void> voidFuture([&foo]() { foo = 7; }, tasks);\n  EXPECT_TRUE(voidFuture.valid());\n  voidFuture.get();\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture([]() { return 33; }, tasks);\n  EXPECT_TRUE(intFuture.valid());\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture([&refTo]() -> int& { return refTo; }, tasks);\n  EXPECT_TRUE(refFuture.valid());\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, TaskSetForceQueuing) {\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n  int foo = 10;\n  dispenso::Future<void> voidFuture([&foo]() { foo = 7; }, tasks, std::launch::async);\n  EXPECT_TRUE(voidFuture.valid());\n  voidFuture.get();\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture([]() { return 33; }, tasks, std::launch::async);\n  EXPECT_TRUE(intFuture.valid());\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture([&refTo]() -> int& { return refTo; }, tasks, std::launch::async);\n  EXPECT_TRUE(refFuture.valid());\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, TaskSetWaitImpliesImmediatelyAvailable) {\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n  int foo = 10;\n  dispenso::Future<void> voidFuture([&foo]() { foo = 7; }, tasks);\n  EXPECT_TRUE(voidFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, voidFuture.wait_for(std::chrono::microseconds(1)));\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture([]() { return 33; }, tasks);\n  EXPECT_TRUE(intFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, intFuture.wait_for(std::chrono::microseconds(1)));\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture([&refTo]() -> int& { return refTo; }, tasks);\n  EXPECT_TRUE(refFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(refFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, refFuture.wait_for(std::chrono::microseconds(1)));\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, ConcurrentTaskSetWaitImpliesImmediatelyAvailable) {\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  int foo = 10;\n  dispenso::Future<void> voidFuture([&foo]() { foo = 7; }, tasks);\n  EXPECT_TRUE(voidFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, voidFuture.wait_for(std::chrono::microseconds(1)));\n  EXPECT_EQ(foo, 7);\n\n  dispenso::Future<int> intFuture([]() { return 33; }, tasks, std::launch::async);\n  EXPECT_TRUE(intFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, intFuture.wait_for(std::chrono::microseconds(1)));\n  int result = intFuture.get();\n  EXPECT_EQ(result, 33);\n\n  int refTo = 77;\n  dispenso::Future<int&> refFuture([&refTo]() -> int& { return refTo; }, tasks);\n  EXPECT_TRUE(refFuture.valid());\n  tasks.wait();\n  EXPECT_TRUE(refFuture.is_ready());\n  EXPECT_EQ(std::future_status::ready, refFuture.wait_for(std::chrono::microseconds(1)));\n  int& ref = refFuture.get();\n  EXPECT_EQ(&ref, &refTo);\n  EXPECT_EQ(77, ref);\n}\n\nTEST(Future, LongRunMultipleWaitFor) {\n  std::atomic<int> synchronizer(0);\n  dispenso::Future<int> intFuture(\n      [&synchronizer]() {\n        while (synchronizer.load(std::memory_order_relaxed) < 10) {\n        }\n        return 77;\n      },\n      dispenso::globalThreadPool(),\n      std::launch::async,\n      // Note that kNotDeferred is required in this case, because otherwise the functor could run on\n      // the current thread in wait_for below, which will hang because the synchronizer will never\n      // be incemented.  This is not a common pattern, but it is the reason why kNotDeferred exists.\n      dispenso::kNotDeferred);\n\n  size_t loopCount = 0;\n  while (intFuture.wait_for(std::chrono::milliseconds(1)) != std::future_status::ready) {\n    synchronizer.fetch_add(1, std::memory_order_relaxed);\n    ++loopCount;\n  }\n  int result = intFuture.get();\n\n  EXPECT_GE(loopCount, 10);\n  EXPECT_EQ(77, result);\n}\n\nTEST(Future, ShareInnerScopeWaits) {\n  dispenso::Future<int> intFuture([]() { return 7; }, dispenso::globalThreadPool());\n\n  const int* address;\n  {\n    auto sharedFuture = intFuture;\n\n    EXPECT_EQ(7, sharedFuture.get());\n    address = &sharedFuture.get();\n  }\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_EQ(address, &intFuture.get());\n}\n\nTEST(Future, BasicLoop) {\n  constexpr int kWorkItems = 10000;\n  std::vector<dispenso::Future<int>> outputs;\n\n  dispenso::ThreadPool pool(10);\n  for (int i = 0; i < kWorkItems; ++i) {\n    outputs.emplace_back([i]() { return i * i; }, pool);\n  }\n\n  int i = 0;\n  for (auto& o : outputs) {\n    EXPECT_EQ(o.get(), i * i);\n    ++i;\n  }\n}\n\nTEST(Future, CheckBackwards) {\n  constexpr int kWorkItems = 10000;\n  std::vector<dispenso::Future<int>> outputs;\n\n  dispenso::ThreadPool pool(10);\n  for (int i = 0; i < kWorkItems; ++i) {\n    outputs.emplace_back([i]() { return i * i; }, pool);\n  }\n\n  for (size_t i = kWorkItems; i--;) {\n    EXPECT_EQ(outputs[i].get(), i * i);\n  }\n}\n\nTEST(Future, Async) {\n  int value = 0;\n  auto voidFuture = dispenso::async([&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async([]() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async([&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotDeferred) {\n  int value = 0;\n  auto voidFuture = dispenso::async(dispenso::kNotDeferred, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(dispenso::kNotDeferred, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(dispenso::kNotDeferred, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotAsync) {\n  int value = 0;\n  auto voidFuture = dispenso::async(dispenso::kNotAsync, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(dispenso::kNotAsync, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(dispenso::kNotAsync, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncSpecifyThreadPool) {\n  dispenso::ThreadPool pool(4);\n  int value = 0;\n  auto voidFuture = dispenso::async(pool, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(pool, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(pool, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotDeferredSpecifyThreadPool) {\n  dispenso::ThreadPool pool(4);\n  int value = 0;\n  auto voidFuture = dispenso::async(pool, dispenso::kNotDeferred, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(pool, dispenso::kNotDeferred, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture =\n      dispenso::async(pool, dispenso::kNotDeferred, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotAsyncSpecifyThreadPool) {\n  dispenso::ThreadPool pool(4);\n  int value = 0;\n  auto voidFuture = dispenso::async(pool, dispenso::kNotAsync, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(pool, dispenso::kNotAsync, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(pool, dispenso::kNotAsync, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncSpecifyNewThread) {\n  int value = 0;\n  auto voidFuture = dispenso::async(dispenso::kNewThreadInvoker, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture = dispenso::async(dispenso::kNewThreadInvoker, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture =\n      dispenso::async(dispenso::kNewThreadInvoker, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotDeferredSpecifyNewThread) {\n  int value = 0;\n  auto voidFuture = dispenso::async(\n      dispenso::kNewThreadInvoker, dispenso::kNotDeferred, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture =\n      dispenso::async(dispenso::kNewThreadInvoker, dispenso::kNotDeferred, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(\n      dispenso::kNewThreadInvoker, dispenso::kNotDeferred, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotAsyncSpecifyNewThread) {\n  int value = 0;\n  auto voidFuture =\n      dispenso::async(dispenso::kNewThreadInvoker, dispenso::kNotAsync, [&value]() { value = 66; });\n  voidFuture.get();\n  EXPECT_EQ(66, value);\n\n  auto intFuture =\n      dispenso::async(dispenso::kNewThreadInvoker, dispenso::kNotAsync, []() { return 77; });\n  EXPECT_EQ(77, intFuture.get());\n\n  auto refFuture = dispenso::async(\n      dispenso::kNewThreadInvoker, dispenso::kNotAsync, [&value]() -> int& { return value; });\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncSpecifyTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, []() { return 77; });\n  auto refFuture = dispenso::async(tasks, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotDeferredSpecifyTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, dispenso::kNotDeferred, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, dispenso::kNotDeferred, []() { return 77; });\n  auto refFuture =\n      dispenso::async(tasks, dispenso::kNotDeferred, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotAsyncSpecifyTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, dispenso::kNotAsync, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, dispenso::kNotAsync, []() { return 77; });\n  auto refFuture =\n      dispenso::async(tasks, dispenso::kNotAsync, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncSpecifyConcurrentTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, []() { return 77; });\n  auto refFuture = dispenso::async(tasks, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotDeferredSpecifyConcurrentTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, dispenso::kNotDeferred, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, dispenso::kNotDeferred, []() { return 77; });\n  auto refFuture =\n      dispenso::async(tasks, dispenso::kNotDeferred, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nTEST(Future, AsyncNotAsyncSpecifyConcurrentTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n  int value = 0;\n  auto voidFuture = dispenso::async(tasks, dispenso::kNotAsync, [&value]() { value = 66; });\n  auto intFuture = dispenso::async(tasks, dispenso::kNotAsync, []() { return 77; });\n  auto refFuture =\n      dispenso::async(tasks, dispenso::kNotAsync, [&value]() -> int& { return value; });\n  tasks.wait();\n  EXPECT_TRUE(voidFuture.is_ready());\n  EXPECT_TRUE(intFuture.is_ready());\n  EXPECT_TRUE(refFuture.is_ready());\n\n  EXPECT_EQ(66, value);\n  EXPECT_EQ(77, intFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n}\n\nstruct Node {\n  int value;\n  std::unique_ptr<Node> left, right;\n};\n\nstatic void validateTree(Node* node, int val, int depth) {\n  if (!node) {\n    return;\n  }\n\n  EXPECT_EQ(node->value, val);\n\n  validateTree(node->left.get(), val + depth, depth + 1);\n  validateTree(node->right.get(), val + depth, depth + 1);\n}\n\nstatic void buildTree(Node* node, int depth) {\n  if (depth == 16) {\n    return;\n  }\n\n  node->left = std::make_unique<Node>();\n  node->right = std::make_unique<Node>();\n  node->left->value = node->right->value = node->value + depth;\n  auto lres = dispenso::async([left = node->left.get(), depth]() { buildTree(left, depth + 1); });\n  auto rres =\n      dispenso::async([right = node->right.get(), depth]() { buildTree(right, depth + 1); });\n\n  lres.get();\n  rres.get();\n}\n\nTEST(Future, RecursivelyBuildTree) {\n  Node root;\n  root.value = 77;\n  buildTree(&root, 0);\n\n  validateTree(&root, 77, 0);\n}\n\nTEST(Future, BasicThenUsage) {\n  int value;\n  auto voidFuture = dispenso::async([]() {\n                      return 77;\n                    }).then([&value](dispenso::Future<int>&& parent) { value = parent.get(); });\n  voidFuture.get();\n  EXPECT_EQ(77, value);\n  auto intFuture = dispenso::async([]() { return 55; }).then([](dispenso::Future<int>&& parent) {\n    return parent.get();\n  });\n  EXPECT_EQ(55, intFuture.get());\n  auto int2Future = dispenso::async([&value]() -> int& {\n                      return value;\n                    }).then([](dispenso::Future<int&>&& parent) { return parent.get(); });\n  EXPECT_EQ(77, int2Future.get());\n\n  auto refFuture = dispenso::async([&value]() -> int& {\n                     return value;\n                   }).then([](dispenso::Future<int&>&& parent) -> int& { return parent.get(); });\n  EXPECT_EQ(77, refFuture.get());\n  EXPECT_EQ(&value, &refFuture.get());\n\n  intFuture = dispenso::async([&value]() {\n                value = 33;\n              }).then([&value](dispenso::Future<void>&& /*parent*/) { return value; });\n  EXPECT_EQ(33, intFuture.get());\n\n  int* valuePtr;\n  voidFuture = dispenso::async([&value]() -> int& {\n                 return value;\n               }).then([&valuePtr](dispenso::Future<int&>&& parent) { valuePtr = &parent.get(); });\n  voidFuture.get();\n  EXPECT_EQ(valuePtr, &value);\n}\n\nTEST(Future, LongerThenChain) {\n  int inval = 123;\n  int outval;\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4172) // returning address of local variable or temporary\n#endif\n  auto intFuture = dispenso::async([&inval]() -> const int& {\n                     return inval;\n                   }).then([](dispenso::Future<const int&>&& parent) {\n                       return parent.get();\n                     }).then([&outval](dispenso::Future<int>&& parent) {\n    outval = parent.get();\n    return parent.get();\n  });\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n  EXPECT_EQ(inval, intFuture.get());\n  EXPECT_EQ(inval, outval);\n}\n\nTEST(Future, MultiThenReadyAllInline) {\n  dispenso::Future<int> intFuture = dispenso::make_ready_future(128);\n  auto a = intFuture.then(\n      [](dispenso::Future<int>&& parent) { return parent.get(); }, dispenso::kImmediateInvoker);\n  auto b = intFuture.then(\n      [](dispenso::Future<int>&& parent) { return parent.get() * parent.get(); },\n      dispenso::kImmediateInvoker);\n  EXPECT_EQ(intFuture.get(), 128);\n  EXPECT_EQ(a.get(), 128);\n  EXPECT_EQ(b.get(), 128 * 128);\n}\n\nTEST(Future, MultiThenReadyDelayedOrigin) {\n  dispenso::Future<int> intFuture = dispenso::async([]() {\n    std::this_thread::sleep_for(std::chrono::milliseconds(5));\n    return 128;\n  });\n  auto a = intFuture.then(\n      [](dispenso::Future<int>&& parent) { return parent.get(); }, dispenso::kImmediateInvoker);\n  auto b = intFuture.then(\n      [](dispenso::Future<int>&& parent) { return parent.get() * parent.get(); },\n      dispenso::kImmediateInvoker);\n  EXPECT_EQ(intFuture.get(), 128);\n  EXPECT_EQ(a.get(), 128);\n  EXPECT_EQ(b.get(), 128 * 128);\n}\n\nTEST(Future, MultiThenReadyDelayedOriginNotImmediateThen) {\n  dispenso::Future<int> intFuture = dispenso::async([]() {\n    std::this_thread::sleep_for(std::chrono::milliseconds(5));\n    return 128;\n  });\n  auto a = intFuture.then([](dispenso::Future<int>&& parent) { return parent.get(); });\n  auto b =\n      intFuture.then([](dispenso::Future<int>&& parent) { return parent.get() * parent.get(); });\n  EXPECT_EQ(intFuture.get(), 128);\n  EXPECT_EQ(a.get(), 128);\n  EXPECT_EQ(b.get(), 128 * 128);\n}\n\nTEST(Future, MultiThenReadyDelayedOriginTightLoop) {\n  std::atomic<bool> originReady{false};\n  dispenso::Future<int> intFuture = dispenso::async([&originReady]() {\n    std::this_thread::sleep_for(std::chrono::milliseconds(1));\n    originReady.store(true);\n    return 128;\n  });\n\n  std::vector<dispenso::Future<int>> futureVec;\n\n  int extraLoops = 100;\n  while (true) {\n    futureVec.emplace_back(\n        intFuture.then([](dispenso::Future<int>&& parent) { return parent.get() * parent.get(); }));\n    if (originReady.load(std::memory_order_relaxed)) {\n      if (extraLoops) {\n        --extraLoops;\n      } else {\n        break;\n      }\n    }\n  }\n\n  EXPECT_GE(futureVec.size(), 101);\n\n  for (auto& f : futureVec) {\n    EXPECT_EQ(f.get(), 128 * 128);\n  }\n}\n\nTEST(Future, ImmediateInvoker) {\n  // Don't write code like this in real life.  It is (much) cheaper to use make_ready_future.\n  dispenso::Future<int> future([]() { return 333; }, dispenso::kImmediateInvoker);\n  EXPECT_TRUE(future.is_ready());\n  EXPECT_EQ(333, future.get());\n\n  int val = 5;\n  dispenso::Future<void> vfuture([&val]() { val = 7; }, dispenso::kImmediateInvoker);\n  EXPECT_TRUE(vfuture.is_ready());\n  EXPECT_EQ(7, val);\n}\n\nTEST(Future, NewThreadInvoker) {\n  // Nearly always it should be better to use async/ThreadPool/TaskSet, but there may be occasions\n  // where you actually want the work done on a new thread.\n  dispenso::Future<int> future([]() { return 333; }, dispenso::kNewThreadInvoker);\n  EXPECT_EQ(333, future.get());\n}\n\n#if defined(__cpp_exceptions)\nTEST(Future, SimpleExceptions) {\n  bool handledException = false;\n  auto intFuture = dispenso::async([]() {\n    throw(std::logic_error(\"oops\"));\n    return 333;\n  });\n\n  try {\n    EXPECT_EQ(777, intFuture.get());\n  } catch (const std::logic_error&) {\n    handledException = true;\n  }\n  EXPECT_TRUE(handledException);\n}\n\nTEST(Future, SimpleExceptionsReference) {\n  bool handledException = false;\n  int val = 333;\n  auto refFuture = dispenso::async([&val]() -> int& {\n    throw(std::logic_error(\"oops\"));\n    return val;\n  });\n\n  try {\n    EXPECT_EQ(777, refFuture.get());\n  } catch (const std::logic_error&) {\n    handledException = true;\n  }\n  EXPECT_TRUE(handledException);\n}\n\nTEST(Future, SimpleExceptionsVoid) {\n  bool handledException = false;\n  int val = 333;\n  auto voidFuture = dispenso::async([]() { throw(std::logic_error(\"oops\")); });\n\n  try {\n    voidFuture.get();\n    EXPECT_EQ(999, val);\n  } catch (const std::logic_error&) {\n    handledException = true;\n  }\n  EXPECT_TRUE(handledException);\n}\n\nTEST(Future, ThenExceptions) {\n  bool handledException = false;\n  auto intFuture = dispenso::async([]() {\n    throw(std::logic_error(\"oops\"));\n    return 333;\n  });\n\n  try {\n    auto resultingFuture = intFuture.then([](auto&& parent) { return parent.get(); });\n\n    EXPECT_EQ(777, resultingFuture.get());\n  } catch (const std::logic_error&) {\n    handledException = true;\n  }\n  EXPECT_TRUE(handledException);\n}\n\nstruct SomeType {\n  SomeType(int init) : ptr(new int(init)) {}\n\n  SomeType(const SomeType& oth) : ptr(new int(*oth.ptr)) {}\n\n  SomeType& operator=(const SomeType& oth) {\n    if (&oth != this) {\n      ptr = new int(*oth.ptr);\n    }\n    return *this;\n  }\n\n  ~SomeType() {\n    delete ptr;\n  }\n  int* ptr;\n};\n\nTEST(Future, ExceptionShouldntDestroyResultIfNotCreated) {\n  auto noExcept = dispenso::async([]() { return SomeType(5); });\n\n  auto res = noExcept.get();\n  EXPECT_EQ(*res.ptr, 5);\n\n  auto withExcept = dispenso::async([]() {\n    throw(std::logic_error(\"oops\"));\n    return SomeType(5);\n  });\n\n  bool handledException = false;\n  try {\n    res = withExcept.get();\n    EXPECT_EQ(777, *res.ptr);\n  } catch (const std::logic_error&) {\n    handledException = true;\n  }\n  EXPECT_TRUE(handledException);\n}\n#endif //__cpp_exceptions\n\nTEST(Future, WhenAllEmptyVector) {\n  std::deque<dispenso::Future<int>> items;\n  auto dummy = dispenso::when_all(items.begin(), items.end()).then([](auto&& readyFutures) {\n    EXPECT_TRUE(readyFutures.is_ready());\n    auto& vec = readyFutures.get();\n    EXPECT_EQ(0, vec.size());\n  });\n\n  dummy.wait();\n}\n\nTEST(Future, WhenAllVector) {\n  constexpr int kWorkItems = 10000;\n  std::deque<dispenso::Future<int>> items;\n\n  dispenso::ThreadPool pool(10);\n  int64_t expectedSum = 0;\n  for (int i = 0; i < kWorkItems; ++i) {\n    items.emplace_back([i]() { return i * i; }, pool);\n    expectedSum += i * i;\n  }\n\n  auto finalSum = dispenso::when_all(items.begin(), items.end()).then([](auto&& readyFutures) {\n    EXPECT_TRUE(readyFutures.is_ready());\n    auto& vec = readyFutures.get();\n    int64_t sum = 0;\n    for (auto& f : vec) {\n      EXPECT_TRUE(f.is_ready());\n      sum += f.get();\n    }\n    return sum;\n  });\n\n  EXPECT_EQ(finalSum.get(), expectedSum);\n}\n\nTEST(Future, WhenAllEmptyTuple) {\n  auto dummy =\n      dispenso::when_all().then([](auto&& readyFutures) { EXPECT_TRUE(readyFutures.is_ready()); });\n  dummy.wait();\n}\n\nTEST(Future, WhenAllTuple) {\n  int value = 16;\n  int value2 = 1024;\n\n  dispenso::Future<int> intFuture([]() { return 77; }, dispenso::globalThreadPool());\n  dispenso::Future<void> voidFuture([&value]() { value = 88; }, dispenso::globalThreadPool());\n  dispenso::Future<float> floatFuture([]() { return 99.0f; }, dispenso::globalThreadPool());\n  dispenso::Future<int&> refFuture(\n      [&value2]() -> int& { return value2; }, dispenso::globalThreadPool());\n\n  auto finalSum = dispenso::when_all(intFuture, voidFuture, floatFuture, refFuture)\n                      .then([&value, &value2](auto&& readyFutures) {\n                        EXPECT_TRUE(readyFutures.is_ready());\n\n                        auto& tuple = readyFutures.get();\n                        EXPECT_EQ(std::get<0>(tuple).get(), 77);\n                        EXPECT_EQ(value, 88);\n                        EXPECT_EQ(std::get<2>(tuple).get(), 99.0f);\n                        EXPECT_EQ(&std::get<3>(tuple).get(), &value2);\n                        return std::get<0>(tuple).get() + value +\n                            static_cast<int>(std::get<2>(tuple).get()) + std::get<3>(tuple).get();\n                      });\n\n  EXPECT_EQ(finalSum.get(), 1288);\n}\n\ninline std::unique_ptr<Node> nodeMove(const std::unique_ptr<Node>& current) {\n  return std::move(const_cast<std::unique_ptr<Node>&>(current));\n}\n\nstatic dispenso::Future<std::unique_ptr<Node>> makeTree(\n    uint32_t depth,\n    std::atomic<uint32_t>& cur) {\n  --depth;\n  auto node = std::make_unique<Node>();\n  node->value = static_cast<int>(cur.fetch_add(1, std::memory_order_relaxed));\n  if (!depth) {\n    return dispenso::make_ready_future(std::move(node));\n  }\n\n  // TODO(bbudge): Can we make this nicer via unwrapping constructor?\n  auto left = dispenso::async([depth, &cur]() { return makeTree(depth, cur); });\n  auto right = dispenso::async([depth, &cur]() { return makeTree(depth, cur); });\n\n  return dispenso::when_all(left, right).then([node = std::move(node)](auto&& both) mutable {\n    auto& tuple = both.get();\n    auto& futFutLeft = std::get<0>(tuple);\n    auto& futFutRight = std::get<1>(tuple);\n    node->left = nodeMove(futFutLeft.get().get());\n    node->right = nodeMove(futFutRight.get().get());\n    return std::move(node);\n  });\n}\n\nstatic void fillVector(std::unique_ptr<Node>& node, std::vector<uint32_t>& values) {\n  if (!node) {\n    return;\n  }\n\n  size_t val = static_cast<size_t>(node->value);\n\n  if (values.size() <= val) {\n    values.resize(val + 1, 0);\n  }\n  ++values[val];\n  fillVector(node->left, values);\n  fillVector(node->right, values);\n}\n\nTEST(Future, WhenAllTreeBuild) {\n  std::atomic<uint32_t> val(0);\n  auto result = makeTree(6, val);\n\n  std::vector<uint32_t> values(16, 0);\n\n  std::unique_ptr<Node> root = nodeMove(result.get());\n\n  fillVector(root, values);\n\n  for (auto& v : values) {\n    EXPECT_EQ(v, 1);\n  }\n}\n\nstatic dispenso::Future<std::unique_ptr<Node>> makeTreeIters(\n    uint32_t depth,\n    std::atomic<uint32_t>& cur) {\n  --depth;\n  auto node = std::make_unique<Node>();\n  node->value = static_cast<int>(cur.fetch_add(1, std::memory_order_relaxed));\n  if (!depth) {\n    return dispenso::make_ready_future(std::move(node));\n  }\n\n  // TODO(bbudge): Can we make this nicer via unwrapping constructor?\n  auto left = dispenso::async([depth, &cur]() { return makeTree(depth, cur); });\n  auto right = dispenso::async([depth, &cur]() { return makeTree(depth, cur); });\n\n  std::array<decltype(left), 2> children = {left, right};\n\n  return dispenso::when_all(std::begin(children), std::end(children))\n      .then([node = std::move(node)](auto&& both) mutable {\n        auto& vec = both.get();\n        EXPECT_EQ(vec.size(), 2);\n        auto& futFutLeft = vec[0];\n        auto& futFutRight = vec[1];\n        node->left = nodeMove(futFutLeft.get().get());\n        node->right = nodeMove(futFutRight.get().get());\n        return std::move(node);\n      });\n}\n\nTEST(Future, WhenAllTreeBuildIters) {\n  std::atomic<uint32_t> val(0);\n  auto result = makeTreeIters(6, val);\n\n  std::vector<uint32_t> values(16, 0);\n\n  std::unique_ptr<Node> root = nodeMove(result.get());\n\n  fillVector(root, values);\n\n  for (auto& v : values) {\n    EXPECT_EQ(v, 1);\n  }\n}\n\n// Pretty convoluted, but there was a bug where taskset wait does not imply the future is finished.\nTEST(Future, TaskSetWaitImpliesFinished) {\n  std::atomic<int> status(0);\n  std::atomic<int> sidelineResult(0);\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n\n  std::thread waiterThread([&tasks, &status, &sidelineResult]() {\n    while (status.load(std::memory_order_acquire) == 0) {\n    }\n    tasks.wait();\n    EXPECT_EQ(sidelineResult.load(std::memory_order_acquire), 1);\n  });\n\n  dispenso::Future<int> intFuture(\n      [&sidelineResult, &status]() {\n        status.store(1, std::memory_order_release);\n        std::this_thread::sleep_for(std::chrono::milliseconds(50));\n        sidelineResult.store(1, std::memory_order_release);\n        return 77;\n      },\n      tasks);\n\n  EXPECT_EQ(77, intFuture.get());\n\n  waiterThread.join();\n}\n\nTEST(Future, TaskSetWaitImpliesWhenAllFinished) {\n  std::vector<dispenso::Future<int>> futures;\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n  for (int i = 0; i < 100; ++i) {\n    futures.emplace_back(dispenso::Future<int>([i]() { return i; }, taskSet));\n  }\n\n  auto result = dispenso::when_all(taskSet, futures.begin(), futures.end())\n                    .then(\n                        [](auto&& future) {\n                          auto& vec = future.get();\n                          int total = 0;\n                          for (auto& f : vec) {\n                            total += f.get();\n                          }\n                        },\n                        taskSet);\n\n  taskSet.wait();\n  EXPECT_TRUE(result.is_ready());\n}\n\nTEST(Future, ConcurrentTaskSetWaitImpliesWhenAllFinished) {\n  std::vector<dispenso::Future<int>> futures;\n  dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n  for (int i = 0; i < 100; ++i) {\n    futures.emplace_back(dispenso::Future<int>([i]() { return i; }, taskSet));\n  }\n\n  auto result = dispenso::when_all(taskSet, futures.begin(), futures.end())\n                    .then(\n                        [](auto&& future) {\n                          auto& vec = future.get();\n                          int total = 0;\n                          for (auto& f : vec) {\n                            total += f.get();\n                          }\n                        },\n                        taskSet);\n\n  taskSet.wait();\n  EXPECT_TRUE(result.is_ready());\n}\n\nTEST(Future, Copy) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n\n    const std::shared_ptr<int>& sp2 = fut.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    auto fut2 = fut;\n\n    const std::shared_ptr<int>& sp2 = fut2.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    decltype(fut) fut2;\n    fut2 = fut;\n\n    const std::shared_ptr<int>& sp2 = fut2.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n}\n\nTEST(Future, Move) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n\n    const std::shared_ptr<int>& sp2 = fut.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    auto fut2 = std::move(fut);\n\n    EXPECT_FALSE(fut.valid());\n\n    const std::shared_ptr<int>& sp2 = fut2.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    decltype(fut) fut2;\n    fut2 = std::move(fut);\n\n    EXPECT_FALSE(fut.valid());\n\n    const std::shared_ptr<int>& sp2 = fut2.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    decltype(fut) fut2;\n    fut2 = std::move(fut);\n\n    EXPECT_FALSE(fut.valid());\n\n    const std::shared_ptr<int>& sp2 = fut2.get();\n    EXPECT_EQ(*sp2, 5);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n\n  EXPECT_EQ(sp.use_count(), 1);\n}\n\nTEST(Future, ThenRefCountImmediate) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    fut = fut.then(\n        [](auto&& prev) {\n          auto sp2 = prev.get();\n          *sp2 = 7;\n          return sp2;\n        },\n        dispenso::kImmediateInvoker);\n\n    const std::shared_ptr<int>& sp3 = fut.get();\n    EXPECT_EQ(*sp3, 7);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n}\n\nTEST(Future, MoveThenRefCountImmediate) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    auto fut = dispenso::make_ready_future(sp);\n    fut = std::move(fut).then(\n        [](auto&& prev) {\n          auto sp2 = prev.get();\n          *sp2 = 7;\n          return sp2;\n        },\n        dispenso::kImmediateInvoker);\n\n    const std::shared_ptr<int>& sp2 = fut.get();\n    EXPECT_EQ(*sp2, 7);\n    EXPECT_EQ(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n}\n\nTEST(Future, ThenRefCountThreadPool) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    dispenso::ThreadPool pool(1);\n    {\n      auto fut = dispenso::make_ready_future(sp);\n      fut = fut.then(\n          [](auto&& prev) {\n            auto sp2 = prev.get();\n            *sp2 = 7;\n            return sp2;\n          },\n          pool);\n\n      const std::shared_ptr<int>& sp3 = fut.get();\n      EXPECT_EQ(*sp3, 7);\n      EXPECT_EQ(sp.use_count(), 2);\n    }\n    // Warning, implementation detail :)\n    // At this point, it is possible that the second future still has a reference count > 0, as it\n    // is held in the OnceFunction submitted to the pool.  If the pool hasn't executed the\n    // OnceFunction yet, the sp.use_count() will be 2.  If it has, it will be 1.\n    EXPECT_LE(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n}\n\nTEST(Future, MoveThenRefCountThreadPool) {\n  std::shared_ptr<int> sp = std::make_shared<int>(5);\n\n  {\n    dispenso::ThreadPool pool(1);\n    {\n      auto fut = dispenso::make_ready_future(sp);\n      fut = std::move(fut).then(\n          [](auto&& prev) {\n            auto sp2 = prev.get();\n            *sp2 = 7;\n            return sp2;\n          },\n          pool);\n\n      const std::shared_ptr<int>& sp2 = fut.get();\n      EXPECT_EQ(*sp2, 7);\n      EXPECT_EQ(sp.use_count(), 2);\n    }\n    // Warning, implementation detail :)\n    // At this point, it is possible that the second future still has a reference count > 0, as it\n    // is held in the OnceFunction submitted to the pool.  If the pool hasn't executed the\n    // OnceFunction yet, the sp.use_count() will be 2.  If it has, it will be 1.\n    EXPECT_LE(sp.use_count(), 2);\n  }\n  EXPECT_EQ(sp.use_count(), 1);\n}\n"
  },
  {
    "path": "tests/graph_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <numeric>\n#include <random>\n\n#include <dispenso/graph.h>\n#include <dispenso/graph_executor.h>\n#include <gtest/gtest.h>\n\nTEST(Graph, Simple) {\n  // ┌─────────┐     ┌─────────┐     ┌─────────┐\n  // │ 0: v+=1 │ ──▶ │ 1: v*=2 │ ──▶ │ 4: v+=p │\n  // └─────────┘     └─────────┘     └─────────┘\n  //                                   ▲\n  // ┌─────────┐     ┌─────────┐       │\n  // │ 2: p+=4 │ ──▶ │ 3: p/=2 │ ──────┘\n  // └─────────┘     └─────────┘\n  float v = 0.f;\n  float p = 0.f;\n  dispenso::Graph g;\n\n  dispenso::Node& N0 = g.addNode([&v]() { v += 1; });\n  dispenso::Node& N1 = g.addNode([&v]() { v *= 2; });\n  dispenso::Node& N2 = g.addNode([&p]() { p += 8; });\n  dispenso::Node& N3 = g.addNode([&p]() { p /= 2; });\n  dispenso::Node& N4 = g.addNode([&p, &v]() { v += p; });\n\n  N4.dependsOn(N1, N3);\n  N1.dependsOn(N0);\n  N3.dependsOn(N2);\n\n  dispenso::ConcurrentTaskSet concurrentTaskSet(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\n  setAllNodesIncomplete(g);\n  concurrentTaskSetExecutor(concurrentTaskSet, g);\n  EXPECT_EQ(v, 6.f);\n\n  v = 0.f;\n  p = 0.f;\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParallelForExecutor parallelForExecutor;\n  setAllNodesIncomplete(g);\n  parallelForExecutor(taskSet, g);\n  EXPECT_EQ(v, 6.f);\n\n  dispenso::SingleThreadExecutor singleThreadExecutor;\n  v = 0.f;\n  p = 0.f;\n  setAllNodesIncomplete(g);\n  singleThreadExecutor(g);\n  EXPECT_EQ(v, 6.f);\n\n  EXPECT_EQ(g.numNodes(), 5);\n}\nenum class EvalMode : uint8_t { singleThread, parallelFor, concurrentTaskSet };\n\ntemplate <class T>\nstd::string modeName(const testing::TestParamInfo<typename T::ParamType>& info) {\n  static std::string names[3] = {\"singleThread\", \"parallelFor\", \"concurrentTaskSet\"};\n  return names[static_cast<uint8_t>(info.param)];\n}\n\nclass Executor {\n public:\n  Executor()\n      : taskSet(dispenso::globalThreadPool()), concurrentTaskSet(dispenso::globalThreadPool()) {}\n\n  template <typename G>\n  void operator()(EvalMode mode, const G& graph) {\n    if (mode == EvalMode::singleThread) {\n      singleThreadExecutor(graph);\n    } else if (mode == EvalMode::parallelFor) {\n      parallelForExecutor(taskSet, graph);\n    } else if (mode == EvalMode::concurrentTaskSet) {\n      concurrentTaskSetExecutor(concurrentTaskSet, graph);\n    }\n  }\n\n private:\n  dispenso::TaskSet taskSet;\n  dispenso::ConcurrentTaskSet concurrentTaskSet;\n  dispenso::ConcurrentTaskSetExecutor concurrentTaskSetExecutor;\n  dispenso::SingleThreadExecutor singleThreadExecutor;\n  dispenso::ParallelForExecutor parallelForExecutor;\n};\n\nstruct SingleThreadMode {\n  static constexpr EvalMode mode = EvalMode::singleThread;\n};\nstruct ParallelForMode {\n  static constexpr EvalMode mode = EvalMode::parallelFor;\n};\nstruct ConcurrentTaskSetMode {\n  static constexpr EvalMode mode = EvalMode::concurrentTaskSet;\n};\n\nclass TwoSubgraphs : public testing::TestWithParam<EvalMode> {\n protected:\n  void SetUp() override {\n    //\n    // ∙----subgraph1---∙ ∙---subgraph2-------∙\n    // ¦ ┌────────────┐ ¦ ¦ ┌───────────────┐ ¦   ┌───────────────────┐\n    // ¦ │ 0: r[0]+=1 │ ──▶ │ 1: r[1]=r[0]*2│ ──▶ │ 4: r[4]=r[1]+r[3] │\n    // ¦ └────────────┘ ¦ ¦ └───────────────┘ ¦   └───────────────────┘\n    // ¦                ¦ ¦                   ¦     ▲\n    // ¦ ┌────────────┐ ¦ ¦ ┌───────────────┐ ¦     │\n    // ¦ │ 2: r[2]+=8 │ ──▶ │ 3: r[3]=r[2]/2│ ──────┘\n    // ¦ └────────────┘ ¦ ¦ └───────────────┘ ¦\n    // ∙----------------∙ ∙-------------------∙\n\n    EXPECT_EQ(graph_.numSubgraphs(), 1); // graph has subgraph 0 by default\n    subgraph1_ = &graph_.addSubgraph();\n    subgraph2_ = &graph_.addSubgraph();\n\n    N_[0] = &subgraph1_->addNode([&]() { r_[0] += 1; });\n    N_[2] = &subgraph1_->addNode([&]() { r_[2] += 8; });\n    N_[1] = &subgraph2_->addNode([&]() { r_[1] += r_[0] * 2; });\n    N_[3] = &subgraph2_->addNode([&]() { r_[3] += r_[2] / 2; });\n    N_[4] = &graph_.addNode([&]() { r_[4] += r_[1] + r_[3]; });\n\n    N_[4]->dependsOn(*N_[1], *N_[3]);\n    N_[1]->dependsOn(*N_[0]);\n    N_[3]->dependsOn(*N_[2]);\n  }\n\n  void evaluateGraph(const dispenso::Graph& graph) {\n    executor_(GetParam(), graph);\n  }\n\n  std::array<float, 5> r_;\n  std::array<dispenso::Node*, 5> N_;\n  dispenso::Graph graph_;\n  dispenso::Subgraph* subgraph1_;\n  dispenso::Subgraph* subgraph2_;\n  Executor executor_;\n  dispenso::ForwardPropagator forwardPropagator_;\n};\nTEST_P(TwoSubgraphs, ReplaceSourceGraph) {\n  setAllNodesIncomplete(graph_);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n  EXPECT_EQ(graph_.numSubgraphs(), 3);\n  EXPECT_EQ(subgraph1_->numNodes(), 2);\n  EXPECT_EQ(subgraph2_->numNodes(), 2);\n\n  subgraph1_->clear();\n  EXPECT_EQ(subgraph1_->numNodes(), 0);\n\n  N_[0] = &subgraph1_->addNode([&]() { r_[0] += 1; });\n  EXPECT_EQ(subgraph1_->numNodes(), 1);\n  N_[2] = &subgraph1_->addNode([&]() { r_[2] += 8; });\n  EXPECT_EQ(subgraph1_->numNodes(), 2);\n  N_[1]->dependsOn(*N_[0]);\n  N_[3]->dependsOn(*N_[2]);\n\n  setAllNodesIncomplete(graph_);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n}\n\nTEST_P(TwoSubgraphs, ReplaceMiddleGraph) {\n  setAllNodesIncomplete(graph_);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  dispenso::Graph movedGraph(std::move(graph_));\n  subgraph2_->clear();\n\n  N_[1] = &subgraph2_->addNode([&]() { r_[1] += r_[0] * 2; });\n  N_[3] = &subgraph2_->addNode([&]() { r_[3] += r_[2] / 2; });\n  N_[1]->dependsOn(*N_[0]);\n  N_[3]->dependsOn(*N_[2]);\n  N_[4]->dependsOn(*N_[1], *N_[3]);\n\n  setAllNodesIncomplete(movedGraph);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(movedGraph);\n  EXPECT_EQ(r_[4], 6.f);\n}\n\nTEST_P(TwoSubgraphs, ReplaceBothGraphs) {\n  setAllNodesIncomplete(graph_);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  subgraph2_->clear();\n  dispenso::Graph movedGraph = std::move(graph_);\n  subgraph1_->clear();\n\n  N_[0] = &subgraph1_->addNode([&]() { r_[0] += 1; });\n  N_[2] = &subgraph1_->addNode([&]() { r_[2] += 8; });\n  N_[1] = &subgraph2_->addNode([&]() { r_[1] += r_[0] * 2; });\n  N_[3] = &subgraph2_->addNode([&]() { r_[3] += r_[2] / 2; });\n\n  N_[4]->dependsOn(*N_[1], *N_[3]);\n  N_[1]->dependsOn(*N_[0]);\n  N_[3]->dependsOn(*N_[2]);\n\n  setAllNodesIncomplete(movedGraph);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(movedGraph);\n  EXPECT_EQ(r_[4], 6.f);\n}\n\nTEST_P(TwoSubgraphs, PartialEvaluation) {\n  setAllNodesIncomplete(graph_);\n  r_ = {0, 0, 0, 0, 0};\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  graph_.forEachNode([](const dispenso::Node& node) { EXPECT_FALSE(!node.isCompleted()); });\n  N_[1]->setIncomplete();\n  r_[1] = r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[2]->setIncomplete();\n  r_[2] = r_[3] = r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[1]->setIncomplete();\n  N_[3]->setIncomplete();\n  r_[1] = r_[3] = r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[4]->setIncomplete();\n  r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[2]->setIncomplete();\n  N_[0]->setIncomplete();\n  r_ = {0, 0, 0, 0, 0};\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[0]->setIncomplete();\n  N_[1]->setIncomplete();\n  N_[4]->setIncomplete();\n  r_[0] = r_[1] = r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n\n  N_[2]->setIncomplete();\n  N_[3]->setIncomplete();\n  N_[4]->setIncomplete();\n  r_[2] = r_[3] = r_[4] = 0;\n  forwardPropagator_(graph_);\n  evaluateGraph(graph_);\n  EXPECT_EQ(r_[4], 6.f);\n}\n\nINSTANTIATE_TEST_SUITE_P(\n    GraphEvaluation,\n    TwoSubgraphs,\n    testing::Values(EvalMode::singleThread, EvalMode::parallelFor, EvalMode::concurrentTaskSet),\n    modeName<TwoSubgraphs>);\n\nclass BiPropGraphTest : public testing::TestWithParam<EvalMode> {\n protected:\n  void SetUp() override {\n    //                                     ┌─────────────────┐\n    //                                     │ 5: m5+=m3*m4    │◀─────────────────────┐\n    //                                     └─────────────────┘                      │\n    //                                       ▲                                      │\n    // ┌−−−−−−−−−−−−−−−−Group1 (a,b)−−−−−−−−−│−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┐ │\n    // ╎ ┌─────────┐     ┌───────────┐     ┌─┴───────────────┐     ┌────────────┐ ╎ │\n    // ╎ │         │     │  0: a+=1  │     │     3: b+=5     │     │            │ ╎ │\n    // ╎ │ 2: a+=3 │     │   b+=5    │     │     m3+=b       │     │ 6: b/=m4   │ ╎ │\n    // ╎ │         │ ◁───┤ m0+=a+b   ├───▷ │                 ├───▷ │            │ ╎ │\n    // ╎ └─────────┘     └─┬─────────┘     └─────────────────┘     └────────────┘ ╎ │\n    // └−−−−−−−−−−−−−−−−−−−│−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−▲−−−−−−−−−−−−┘ │\n    //                     └─────────────────┐                       │              │\n    //                 ┌−−−−−−−Group2 (c)−−−−▼−−−−−−−−−−−−−−−−−┐     │              │\n    //                 ╎ ┌───────────┐     ┌─────────────────┐ ╎   ┌─┴──────────┐   │\n    //                 ╎ │  7: c+=5  ├───▷ │   1: c+=m0      │ ╎   │ 4: m4+=3   ├───┘\n    //                 ╎ └───────────┘     └─────────────────┘ ╎   └────────────┘\n    //                 └−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−┘\n    //  Legend:\n    //  ──▶ Normal dependency\n    //  ──▷ Bidirectional propagation dependency\n    //  m4  variable modified only in node 4\n    N[0] = &g.addNode([&]() {\n      a += 1;\n      b += 5;\n      m0 += a + b;\n    });\n    N[1] = &g.addNode([&]() { c += m0; });\n    N[2] = &g.addNode([&]() { a += 3; });\n    N[3] = &g.addNode([&]() {\n      b += 5;\n      m3 += b;\n    });\n    N[4] = &g.addNode([&]() { m4 += 3; });\n    N[5] = &g.addNode([&]() { m5 += m3 * m4; });\n    N[6] = &g.addNode([&]() { b /= m4; });\n    N[7] = &g.addNode([&]() { c += 5; });\n\n    N[5]->dependsOn(*N[3], *N[4]);\n    N[1]->dependsOn(*N[0]);\n    N[6]->dependsOn(*N[4]);\n\n    N[2]->biPropDependsOn(*N[0]);\n    N[3]->biPropDependsOn(*N[0]);\n    N[6]->biPropDependsOn(*N[3]);\n    N[1]->biPropDependsOn(*N[7]);\n  }\n\n  void checkResults() {\n    EXPECT_EQ(a, 4.f);\n    EXPECT_EQ(b, 10.f / 3.f);\n    EXPECT_EQ(c, 11.f);\n    EXPECT_EQ(m5, 30.f);\n  }\n\n  float a, b, c, m0, m3, m4, m5;\n  dispenso::BiPropGraph g;\n  std::array<dispenso::BiPropNode*, 8> N;\n  Executor executor_;\n  dispenso::ForwardPropagator forwardPropagator_;\n};\n\nTEST_P(BiPropGraphTest, SimpleEvaluation) {\n  a = b = c = m0 = m3 = m4 = m5 = 0.f;\n  setAllNodesIncomplete(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  a = b = c = m0 = m3 = m4 = m5 = 0.f;\n  setAllNodesIncomplete(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[4]->setIncomplete();\n  m5 = m4 = m3 = m0 = a = b = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[1]->setIncomplete();\n  c = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[7]->setIncomplete();\n  c = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[0]->setIncomplete();\n  a = b = c = m0 = m3 = m5 = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[5]->setIncomplete();\n  m5 = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n\n  N[4]->setIncomplete();\n  N[6]->setIncomplete();\n  m5 = m4 = m3 = m0 = a = b = 0.f;\n  forwardPropagator_(g);\n  executor_(GetParam(), g);\n  checkResults();\n}\n\nINSTANTIATE_TEST_SUITE_P(\n    BiPropEvaluation,\n    BiPropGraphTest,\n    testing::Values(EvalMode::singleThread, EvalMode::parallelFor, EvalMode::concurrentTaskSet),\n    modeName<BiPropGraphTest>);\n\ntemplate <class T>\nclass BigTree : public testing::Test {\n protected:\n  static size_t sizeOfLevel(size_t level) {\n    return size_t(1) << (numBits_ - shiftStep_ * level);\n  }\n  void SetUp() override {\n    // the goal of this task is to calculate the sum of the numbers in this array\n    for (size_t level = 1; level < numLevels_; ++level) {\n      const size_t s = sizeOfLevel(level);\n      data_[level].resize(s, size_t(0));\n    }\n\n    // zero level data is input data for calcualtion\n    data_[0].resize(size_t(1) << numBits_);\n    std::iota(data_[0].begin(), data_[0].end(), 0);\n\n    for (size_t level = 1; level < numLevels_; ++level) {\n      SubGraphType* subgraph = &g_.addSubgraph();\n      subgraphs_[level] = subgraph;\n      buildLevel(level);\n    }\n  }\n\n  void rebuildLevel(size_t level) {\n    buildLevel(level);\n    if (level == numLevels_ - 1) {\n      return;\n    }\n\n    const size_t level1 = level + 1;\n    const size_t numNodes = size_t(1) << (numBits_ - shiftStep_ * level1);\n\n    for (size_t n = 0; n < numNodes; ++n) {\n      if (level1 > 1) {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          subgraphs_[level1]->node(n).dependsOn(subgraphs_[level1 - 1]->node(index));\n        }\n      }\n    }\n  }\n\n  void buildLevel(size_t level) {\n    SubGraphType* subgraph = subgraphs_[level];\n\n    const size_t numNodes = size_t(1) << (numBits_ - shiftStep_ * level);\n\n    for (size_t n = 0; n < numNodes; ++n) {\n      subgraph->addNode([this, level, n]() {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          data_[level][n] += data_[level - 1][index];\n        }\n      });\n      if (level > 1) {\n        for (size_t j = 0; j < numPredecessors_; ++j) {\n          const size_t index = (n << shiftStep_) | j;\n          subgraphs_[level]->node(n).dependsOn(subgraphs_[level - 1]->node(index));\n        }\n      }\n    }\n  }\n  static constexpr size_t shiftStep_ = 4; // 4\n  static constexpr size_t numBits_ = 5 * shiftStep_; // 5 // should be divisible by shiftStep\n  static constexpr size_t numPredecessors_ = 1 << shiftStep_;\n  static constexpr size_t startShnft_ = shiftStep_;\n  static constexpr size_t numLevels_ = numBits_ / shiftStep_ + 1;\n  static constexpr size_t level0Size_ = size_t(1) << numBits_;\n\n  using GraphType = std::tuple_element_t<0, T>;\n  using SubGraphType = typename GraphType::SubgraphType;\n  static constexpr EvalMode mode_ = std::tuple_element_t<1, T>::mode;\n\n  std::array<std::vector<size_t>, numLevels_> data_;\n  std::array<SubGraphType*, numLevels_> subgraphs_;\n  GraphType g_;\n  Executor executor_;\n  dispenso::ForwardPropagator forwardPropagator_;\n};\n\nusing GraphCases = ::testing::Types<\n    std::tuple<dispenso::Graph, SingleThreadMode>,\n    std::tuple<dispenso::Graph, ParallelForMode>,\n    std::tuple<dispenso::Graph, ConcurrentTaskSetMode>,\n    std::tuple<dispenso::BiPropGraph, SingleThreadMode>,\n    std::tuple<dispenso::BiPropGraph, ParallelForMode>,\n    std::tuple<dispenso::BiPropGraph, ConcurrentTaskSetMode>>;\n\nTYPED_TEST_SUITE(BigTree, GraphCases, );\n\nTYPED_TEST(BigTree, FullAndPartialEvaluation) {\n  size_t result = std::accumulate(this->data_[0].begin(), this->data_[0].end(), size_t(0));\n\n  setAllNodesIncomplete(this->g_);\n  this->executor_(this->mode_, this->g_);\n\n  EXPECT_EQ(this->data_[this->numLevels_ - 1][0], result);\n\n  std::random_device dev;\n  std::mt19937 rng(dev());\n  std::uniform_int_distribution<std::mt19937::result_type> dist(0, this->level0Size_ - 1);\n  std::uniform_int_distribution<std::mt19937::result_type> numValuesDist(1, this->level0Size_ / 16);\n\n  const size_t numExperiments = 20;\n  for (uint32_t i = 0; i < numExperiments; ++i) {\n    const size_t numValues = numValuesDist(rng);\n\n    for (size_t j = 0; j < numValues; ++j) {\n      const size_t dataIndex = dist(rng);\n      const size_t node1Index = dataIndex >> this->shiftStep_;\n      this->data_[0][dataIndex] = dist(rng);\n      this->subgraphs_[1]->node(node1Index).setIncomplete();\n      // clean up nodes data. We don't touch other nodes' data so that the test fail if we evaluated\n      // more than necessary.\n      for (size_t level = 1; level < this->numLevels_; ++level) {\n        this->data_[level][dataIndex >> (this->shiftStep_ * level)] = 0;\n      }\n    }\n\n    result = std::accumulate(this->data_[0].begin(), this->data_[0].end(), size_t(0));\n\n    this->forwardPropagator_(this->g_);\n    this->executor_(this->mode_, this->g_);\n    EXPECT_EQ(this->data_[this->numLevels_ - 1][0], result);\n  }\n}\n\nTYPED_TEST(BigTree, SubgraphClearAndRebuild) {\n  size_t result = std::accumulate(this->data_[0].begin(), this->data_[0].end(), size_t(0));\n\n  setAllNodesIncomplete(this->g_);\n  this->executor_(this->mode_, this->g_);\n  EXPECT_EQ(this->data_[this->numLevels_ - 1][0], result);\n\n  std::random_device dev;\n  std::mt19937 rng(dev());\n  std::uniform_int_distribution<std::mt19937::result_type> distLevel(1, this->numLevels_ - 1);\n\n  const size_t numExperiments = 20;\n  for (uint32_t i = 0; i < numExperiments; ++i) {\n    const size_t level = distLevel(rng);\n\n    this->subgraphs_[level]->clear();\n    this->rebuildLevel(level);\n    this->forwardPropagator_(this->g_);\n    // clean up nodes data.\n    for (size_t l = level; l < this->numLevels_; ++l) {\n      std::fill(this->data_[l].begin(), this->data_[l].end(), size_t(0));\n    }\n\n    this->executor_(this->mode_, this->g_);\n\n    EXPECT_EQ(this->data_[this->numLevels_ - 1][0], result);\n  }\n}\n\n// Test BiPropNode edge cases to exercise set_union code path\n// This happens when two nodes with existing biPropSets are connected\nTEST(BiPropNode, SetUnionMerge) {\n  dispenso::BiPropGraph g;\n  int a = 0, b = 0, c = 0, d = 0;\n\n  // Create two separate biProp chains first\n  // Chain 1: N0 <-> N1\n  dispenso::BiPropNode& N0 = g.addNode([&]() { a += 1; });\n  dispenso::BiPropNode& N1 = g.addNode([&]() { b += a; });\n  N1.biPropDependsOn(N0);\n\n  // Chain 2: N2 <-> N3\n  dispenso::BiPropNode& N2 = g.addNode([&]() { c += 2; });\n  dispenso::BiPropNode& N3 = g.addNode([&]() { d += c; });\n  N3.biPropDependsOn(N2);\n\n  // Now connect the two chains - this should trigger set_union\n  // because both N1 and N2 already have biPropSets\n  N2.biPropDependsOn(N1);\n\n  // Execute and verify\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 1);\n  EXPECT_EQ(c, 2);\n  EXPECT_EQ(d, 2);\n\n  // Verify that marking one node incomplete propagates to all connected nodes\n  dispenso::ForwardPropagator forwardPropagator;\n  N0.setIncomplete();\n  a = b = c = d = 0;\n  forwardPropagator(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 1);\n  EXPECT_EQ(c, 2);\n  EXPECT_EQ(d, 2);\n}\n\n// Test BiPropNode with node that already has biPropSet connecting to one without\nTEST(BiPropNode, ExistingSetToNew) {\n  dispenso::BiPropGraph g;\n  int a = 0, b = 0, c = 0;\n\n  // Create a biProp chain: N0 <-> N1\n  dispenso::BiPropNode& N0 = g.addNode([&]() { a += 1; });\n  dispenso::BiPropNode& N1 = g.addNode([&]() { b += a; });\n  N1.biPropDependsOn(N0);\n\n  // Create a standalone node N2\n  dispenso::BiPropNode& N2 = g.addNode([&]() { c += b; });\n\n  // Connect N2 to the existing chain - N1 has biPropSet, N2 doesn't\n  N2.biPropDependsOn(N1);\n\n  // Execute and verify\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 1);\n  EXPECT_EQ(c, 1);\n}\n\n// Test BiPropNode with node without biPropSet connecting to one that has it\nTEST(BiPropNode, NewToExistingSet) {\n  dispenso::BiPropGraph g;\n  int a = 0, b = 0, c = 0;\n\n  // Create a biProp chain: N1 <-> N2\n  dispenso::BiPropNode& N1 = g.addNode([&]() { b += 1; });\n  dispenso::BiPropNode& N2 = g.addNode([&]() { c += b; });\n  N2.biPropDependsOn(N1);\n\n  // Create a standalone node N0\n  dispenso::BiPropNode& N0 = g.addNode([&]() { a += 1; });\n\n  // Connect the existing chain to N0 - N1 has biPropSet, N0 doesn't\n  N1.biPropDependsOn(N0);\n\n  // Execute and verify\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 1);\n  EXPECT_EQ(c, 1);\n}\n\n// Test Subgraph accessors: numNodes() and node()\nTEST(Subgraph, AccessorsBasic) {\n  dispenso::Graph g;\n  dispenso::Subgraph& subgraph = g.addSubgraph();\n\n  int a = 0, b = 0, c = 0;\n\n  // Add nodes to the subgraph\n  dispenso::Node& N0 = subgraph.addNode([&]() { a = 1; });\n  dispenso::Node& N1 = subgraph.addNode([&]() { b = 2; });\n  dispenso::Node& N2 = subgraph.addNode([&]() { c = 3; });\n\n  // Test numNodes()\n  EXPECT_EQ(subgraph.numNodes(), 3u);\n\n  // Test node() accessor (non-const)\n  EXPECT_EQ(&subgraph.node(0), &N0);\n  EXPECT_EQ(&subgraph.node(1), &N1);\n  EXPECT_EQ(&subgraph.node(2), &N2);\n\n  // Test const node() accessor\n  const dispenso::Subgraph& constSubgraph = subgraph;\n  EXPECT_EQ(&constSubgraph.node(0), &N0);\n  EXPECT_EQ(&constSubgraph.node(1), &N1);\n  EXPECT_EQ(&constSubgraph.node(2), &N2);\n\n  // Verify nodes work correctly\n  N1.dependsOn(N0);\n  N2.dependsOn(N1);\n\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 2);\n  EXPECT_EQ(c, 3);\n}\n\n// Test Subgraph move constructor\nTEST(Subgraph, MoveConstructor) {\n  dispenso::Graph g;\n\n  // Create a subgraph and add nodes via a function that returns by move\n  auto createSubgraphWithNodes = [&g]() -> dispenso::Subgraph& { return g.addSubgraph(); };\n\n  dispenso::Subgraph& subgraph = createSubgraphWithNodes();\n\n  int x = 0;\n  subgraph.addNode([&]() { x = 42; });\n\n  EXPECT_EQ(subgraph.numNodes(), 1u);\n\n  // Execute to verify the moved subgraph works\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(x, 42);\n}\n\n// Test Graph-level node() accessors that delegate to subgraph 0\nTEST(Graph, NodeAccessors) {\n  dispenso::Graph g;\n\n  int a = 0, b = 0;\n\n  // Add nodes directly to the graph (goes to subgraph 0)\n  dispenso::Node& N0 = g.addNode([&]() { a = 1; });\n  dispenso::Node& N1 = g.addNode([&]() { b = 2; });\n\n  // Test Graph::numNodes()\n  EXPECT_EQ(g.numNodes(), 2u);\n\n  // Test non-const node() accessor\n  EXPECT_EQ(&g.node(0), &N0);\n  EXPECT_EQ(&g.node(1), &N1);\n\n  // Test const node() accessor\n  const dispenso::Graph& constGraph = g;\n  EXPECT_EQ(&constGraph.node(0), &N0);\n  EXPECT_EQ(&constGraph.node(1), &N1);\n\n  // Execute to verify\n  dispenso::SingleThreadExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(g);\n\n  EXPECT_EQ(a, 1);\n  EXPECT_EQ(b, 2);\n}\n\n// Test Graph::subgraph() accessors\nTEST(Graph, SubgraphAccessors) {\n  dispenso::Graph g;\n\n  // Graph starts with subgraph 0\n  EXPECT_EQ(g.numSubgraphs(), 1u);\n\n  // Add more subgraphs\n  dispenso::Subgraph& sg1 = g.addSubgraph();\n  dispenso::Subgraph& sg2 = g.addSubgraph();\n\n  EXPECT_EQ(g.numSubgraphs(), 3u);\n\n  // Test non-const subgraph() accessor\n  EXPECT_EQ(&g.subgraph(1), &sg1);\n  EXPECT_EQ(&g.subgraph(2), &sg2);\n\n  // Test const subgraph() accessor\n  const dispenso::Graph& constGraph = g;\n  EXPECT_EQ(&constGraph.subgraph(1), &sg1);\n  EXPECT_EQ(&constGraph.subgraph(2), &sg2);\n}\n\n// Test Graph::clear() method\nTEST(Graph, ClearMethod) {\n  dispenso::Graph g;\n\n  int x = 0;\n\n  // Add some nodes\n  g.addNode([&]() { x += 1; });\n  g.addNode([&]() { x += 2; });\n  g.addSubgraph();\n\n  EXPECT_EQ(g.numNodes(), 2u);\n  EXPECT_EQ(g.numSubgraphs(), 2u);\n\n  // Clear the graph\n  g.clear();\n\n  // After clear, graph should have 1 empty subgraph\n  EXPECT_EQ(g.numSubgraphs(), 1u);\n  EXPECT_EQ(g.numNodes(), 0u);\n}\n\n#if defined(__cpp_exceptions)\n\n// Exception safety tests for graph executors.\n// Verify that exceptions propagate correctly and that the pool remains usable.\n\nstruct GraphTestException : std::runtime_error {\n  GraphTestException() : std::runtime_error(\"graph test exception\") {}\n};\n\nTEST(GraphExceptionSafety, SingleThreadExecutor) {\n  for (int round = 0; round < 10; ++round) {\n    dispenso::Graph g;\n    int a = 0, b = 0;\n\n    g.addNode([&]() { a = 1; });\n    g.addNode([&]() { throw GraphTestException(); });\n    g.addNode([&]() { b = 2; });\n\n    dispenso::SingleThreadExecutor executor;\n    setAllNodesIncomplete(g);\n    EXPECT_THROW(executor(g), GraphTestException);\n  }\n\n  // Verify pool is still usable after exceptions\n  dispenso::Graph g;\n  int result = 0;\n  g.addNode([&]() { result = 42; });\n\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(tasks, g);\n  EXPECT_EQ(result, 42);\n}\n\nTEST(GraphExceptionSafety, ParallelForExecutor) {\n  for (int round = 0; round < 10; ++round) {\n    dispenso::Graph g;\n    std::atomic<int> count{0};\n\n    // Build a diamond graph:\n    //   N0 -> N1 (throws) -> N3\n    //   N0 -> N2           -> N3\n    dispenso::Node& n0 = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& n1 = g.addNode([&]() { throw GraphTestException(); });\n    dispenso::Node& n2 = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& n3 = g.addNode([&]() { count.fetch_add(1); });\n\n    n1.dependsOn(n0);\n    n2.dependsOn(n0);\n    n3.dependsOn(n1, n2);\n\n    dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n    dispenso::ParallelForExecutor executor;\n    setAllNodesIncomplete(g);\n    EXPECT_THROW(executor(taskSet, g), GraphTestException);\n  }\n\n  // Verify pool is still usable\n  dispenso::Graph g;\n  int result = 0;\n  g.addNode([&]() { result = 99; });\n\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParallelForExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(taskSet, g);\n  EXPECT_EQ(result, 99);\n}\n\nTEST(GraphExceptionSafety, ConcurrentTaskSetExecutor) {\n  for (int round = 0; round < 10; ++round) {\n    dispenso::Graph g;\n    std::atomic<int> count{0};\n\n    // Build a chain to exercise inline continuation:\n    //   N0 -> N1 -> N2 (throws) -> N3\n    dispenso::Node& n0 = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& n1 = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& n2 = g.addNode([&]() { throw GraphTestException(); });\n    dispenso::Node& n3 = g.addNode([&]() { count.fetch_add(1); });\n\n    n1.dependsOn(n0);\n    n2.dependsOn(n1);\n    n3.dependsOn(n2);\n\n    dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    setAllNodesIncomplete(g);\n    EXPECT_THROW(executor(tasks, g), GraphTestException);\n  }\n\n  // Verify pool is still usable\n  dispenso::Graph g;\n  int result = 0;\n  g.addNode([&]() { result = 77; });\n\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(tasks, g);\n  EXPECT_EQ(result, 77);\n}\n\nTEST(GraphExceptionSafety, ConcurrentTaskSetExecutor_InlineContinuation) {\n  // Specifically test the inline continuation path in evaluateNodeConcurrently.\n  // Build a wide fan-out followed by a chain, so some nodes run inline.\n  for (int round = 0; round < 10; ++round) {\n    dispenso::Graph g;\n    std::atomic<int> count{0};\n\n    // Fan-out: root -> {A, B, C, D}\n    // Chain from A: A -> E -> F (throws)\n    dispenso::Node& root = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nA = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nB = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nC = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nD = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nE = g.addNode([&]() { count.fetch_add(1); });\n    dispenso::Node& nF = g.addNode([&]() { throw GraphTestException(); });\n\n    nA.dependsOn(root);\n    nB.dependsOn(root);\n    nC.dependsOn(root);\n    nD.dependsOn(root);\n    nE.dependsOn(nA);\n    nF.dependsOn(nE);\n\n    dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    setAllNodesIncomplete(g);\n    EXPECT_THROW(executor(tasks, g), GraphTestException);\n  }\n\n  // Verify pool is still usable\n  dispenso::Graph g;\n  int result = 0;\n  g.addNode([&]() { result = 55; });\n\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(tasks, g);\n  EXPECT_EQ(result, 55);\n}\n\nTEST(GraphExceptionSafety, ConcurrentTaskSetExecutor_DeepGraphException) {\n  // Build a \"staircase\" graph that would cause deep recursion in\n  // evaluateNodeConcurrently without the depth guard. Each fork node has\n  // 2 ready dependents: a leaf (followed inline by while loop) and the next\n  // fork (scheduled, potentially inlined by CTS → recursion).\n  //\n  //   fork0 → leaf0\n  //   fork0 → fork1 → leaf1\n  //            fork1 → fork2 → leaf2\n  //                     fork2 → fork3 ...\n  //\n  // With depth 2000 and no depth guard, CTS inline execution would create\n  // ~2000 recursive stack frames — enough to overflow worker thread stacks.\n  // The depth guard caps recursion by using ForceQueuingTag beyond the limit.\n  constexpr int kDepth = 2000;\n\n  for (int round = 0; round < 5; ++round) {\n    dispenso::Graph g;\n    std::atomic<int> executed{0};\n    const int throwAt = kDepth / 2;\n\n    // Create fork and leaf nodes\n    std::vector<dispenso::Node*> forks(kDepth);\n    std::vector<dispenso::Node*> leaves(kDepth);\n\n    for (int i = 0; i < kDepth; ++i) {\n      if (i == throwAt) {\n        forks[i] = &g.addNode([&]() {\n          executed.fetch_add(1, std::memory_order_relaxed);\n          throw GraphTestException();\n        });\n      } else {\n        forks[i] = &g.addNode([&]() { executed.fetch_add(1, std::memory_order_relaxed); });\n      }\n      leaves[i] = &g.addNode([&]() { executed.fetch_add(1, std::memory_order_relaxed); });\n    }\n\n    // Wire up: each fork depends on the previous fork\n    // Each leaf depends on its fork\n    // Add leaf dependency FIRST so it becomes the inline continuation,\n    // and next fork becomes the \"scheduled\" dependent.\n    for (int i = 0; i < kDepth; ++i) {\n      leaves[i]->dependsOn(*forks[i]);\n      if (i + 1 < kDepth) {\n        forks[i + 1]->dependsOn(*forks[i]);\n      }\n    }\n\n    dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n    dispenso::ConcurrentTaskSetExecutor executor;\n    setAllNodesIncomplete(g);\n    EXPECT_THROW(executor(tasks, g), GraphTestException);\n  }\n\n  // Verify pool is still usable\n  dispenso::Graph g;\n  int result = 0;\n  g.addNode([&]() { result = 123; });\n\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(tasks, g);\n  EXPECT_EQ(result, 123);\n}\n\n#endif // __cpp_exceptions\n\n// Non-exception deep graph test — verifies depth guard prevents stack overflow\n// and all nodes execute correctly.\nTEST(GraphDepthGuard, ConcurrentTaskSetExecutor_DeepGraph) {\n  constexpr int kDepth = 2000;\n\n  dispenso::Graph g;\n  std::atomic<int> executed{0};\n\n  std::vector<dispenso::Node*> forks(kDepth);\n  std::vector<dispenso::Node*> leaves(kDepth);\n\n  for (int i = 0; i < kDepth; ++i) {\n    forks[i] = &g.addNode([&]() { executed.fetch_add(1, std::memory_order_relaxed); });\n    leaves[i] = &g.addNode([&]() { executed.fetch_add(1, std::memory_order_relaxed); });\n  }\n\n  for (int i = 0; i < kDepth; ++i) {\n    leaves[i]->dependsOn(*forks[i]);\n    if (i + 1 < kDepth) {\n      forks[i + 1]->dependsOn(*forks[i]);\n    }\n  }\n\n  dispenso::ConcurrentTaskSet tasks(dispenso::globalThreadPool());\n  dispenso::ConcurrentTaskSetExecutor executor;\n  setAllNodesIncomplete(g);\n  executor(tasks, g);\n\n  // All 2*kDepth nodes must have executed\n  EXPECT_EQ(executed.load(), 2 * kDepth);\n}\n"
  },
  {
    "path": "tests/greedy_for_ranges_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <list>\n#include <vector>\n\n#include <dispenso/parallel_for.h>\n\n#include <gtest/gtest.h>\n\n#include \"test_tid.h\"\n\nstatic void simpleInner(int w, int y, const std::vector<int>& image, std::atomic<int64_t>& sum) {\n  const int* row = image.data() + y * w;\n  int64_t s = 0;\n  for (int i = 0; i < w; ++i) {\n    s += row[i];\n  }\n  sum.fetch_add(s, std::memory_order_relaxed);\n}\n\nTEST(GreedyForRanges, SimpleLoop) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::parallel_for(0, h, [w, &image, &sum](int y, int yend) {\n    for (; y < yend; ++y) {\n      simpleInner(w, y, image, sum);\n    }\n  });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyForRanges, ShouldNotInvokeIfEmptyRange) {\n  int* myNullPtr = nullptr;\n\n  dispenso::ParForOptions options;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n\n  dispenso::parallel_for(0, 0, [myNullPtr](int i, int /*ie*/) { *myNullPtr = i; }, options);\n\n  options.defaultChunking = dispenso::ParForChunking::kStatic;\n\n  dispenso::parallel_for(0, 0, [myNullPtr](int i, int /*ie*/) { *myNullPtr = i; }, options);\n}\n\ntemplate <typename StateContainer>\nvoid loopWithStateImpl(dispenso::ThreadPool& pool = dispenso::globalThreadPool()) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  dispenso::TaskSet taskSet(pool);\n  StateContainer state;\n  dispenso::parallel_for(\n      taskSet,\n      state,\n      []() { return int64_t{0}; },\n      0,\n      h,\n      [w, &image](int64_t& sum, int y, int yend) {\n        for (; y < yend; ++y) {\n          int* row = image.data() + y * w;\n          int64_t s = 0;\n          for (int i = 0; i < w; ++i) {\n            s += row[i];\n          }\n          sum += s;\n        }\n      });\n\n  int64_t sum = 0;\n  for (int64_t s : state) {\n    sum += s;\n  }\n\n  EXPECT_EQ(sum, w * h * 7);\n}\n\nTEST(GreedyForRanges, LoopWithDequeState) {\n  loopWithStateImpl<std::deque<int64_t>>();\n}\nTEST(GreedyForRanges, LoopWithVectorState) {\n  loopWithStateImpl<std::vector<int64_t>>();\n}\nTEST(GreedyForRanges, LoopWithListState) {\n  loopWithStateImpl<std::list<int64_t>>();\n}\n\nTEST(GreedyForRanges, ConcurrentLoopNoCoordination) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  std::thread tA([w, h, &image, &sumA]() {\n    dispenso::parallel_for(0, h, [w, &image, &sumA](int y, int yend) {\n      for (; y < yend; ++y) {\n        simpleInner(w, y, image, sumA);\n      }\n    });\n  });\n  std::thread tB([w, h, &image, &sumB]() {\n    dispenso::parallel_for(0, h, [w, &image, &sumB](int y, int yend) {\n      for (; y < yend; ++y) {\n        simpleInner(w, y, image, sumB);\n      }\n    });\n  });\n\n  tA.join();\n  tB.join();\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyForRanges, CoordinatedLoops) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      h,\n      [w, &image, &sumA](int y, int yend) {\n        for (; y < yend; ++y) {\n          simpleInner(w, y, image, sumA);\n        }\n      },\n      options);\n\n  dispenso::parallel_for(taskSet, 0, h, [w, &image, &sumB](int y, int yend) {\n    for (; y < yend; ++y) {\n      simpleInner(w, y, image, sumB);\n    }\n  });\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nstatic void concurrentLoop(\n    dispenso::ConcurrentTaskSet& taskSet,\n    int w,\n    int h,\n    const std::vector<int>& image,\n    std::atomic<int64_t>& sum) {\n  dispenso::ParForOptions options;\n  options.wait = false;\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      h,\n      [w, &image, &sum](int y, int yend) {\n        for (; y < yend; ++y) {\n          simpleInner(w, y, image, sum);\n        }\n      },\n      options);\n}\n\nTEST(GreedyForRanges, CoordinatedConcurrentLoops) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n  dispenso::ParForOptions options;\n  options.wait = false;\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      h,\n      [w, &image, &sumA](int y, int yend) {\n        for (; y < yend; ++y) {\n          simpleInner(w, y, image, sumA);\n        }\n      },\n      options);\n\n  std::thread thread(\n      [&taskSet, w, h, &image, &sumB]() { concurrentLoop(taskSet, w, h, image, sumB); });\n  thread.join();\n  taskSet.wait();\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nstatic void\ntestMaxThreads(size_t poolSize, uint32_t maxThreads, bool testStaticChunking, bool testWaitOption) {\n  resetTestTid();\n  size_t numAvailableThreads = poolSize + testWaitOption;\n  std::vector<int> threadLocalSums(numAvailableThreads, 0);\n  dispenso::ThreadPool pool(poolSize);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::ParForOptions options;\n  options.maxThreads = maxThreads;\n  options.wait = testWaitOption;\n  options.defaultChunking =\n      testStaticChunking ? dispenso::ParForChunking::kStatic : dispenso::ParForChunking::kAuto;\n\n  auto func = [&threadLocalSums](int index, int indexEnd) {\n    for (; index < indexEnd; ++index) {\n      assert(index > 0); // for correctness of numNonZero\n      std::this_thread::yield();\n      threadLocalSums[getTestTid()] += index;\n    }\n  };\n\n  dispenso::parallel_for(tasks, 1, 10000, func, options);\n\n  if (!testWaitOption) {\n    // We didn't tell the parallel_for to wait, so we need to do it here to ensure the loop is\n    // complete.\n    tasks.wait();\n  }\n\n  int total = 0;\n  int numNonZero = 0;\n\n  for (size_t i = 0; i < numAvailableThreads; ++i) {\n    numNonZero += threadLocalSums[i] > 0;\n    total += threadLocalSums[i];\n  }\n\n  // 0 indicates serial execution per API spec\n  size_t translatedMaxThreads = maxThreads == 0 ? 1 : maxThreads;\n  EXPECT_LE(numNonZero, std::min((size_t)translatedMaxThreads, numAvailableThreads));\n  EXPECT_EQ(total, 49995000);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsBigPoolStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsBigPoolStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsBigPoolAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsBigPoolAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSmallPoolStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSmallPoolStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSmallPoolAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSmallPoolAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSerialStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSerialStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSerialAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, OptionsMaxThreadsSerialAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyForRanges, NegativeRangeLength) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, 2, -2, [](auto /*index*/, auto /*indexEnd*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyForRanges, NegativeRangeLengthBig) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, 2147483647, -2147483647, [](auto /*index*/, auto /*indexEnd*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyForRanges, ZeroLength2) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, -77, -77, [](auto /*index*/, auto /*indexEnd*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyForRanges, AvoidOverflow1) {\n  std::atomic<uint32_t> count(0);\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(\n      taskSet,\n      std::numeric_limits<int16_t>::min(),\n      std::numeric_limits<int16_t>::max(),\n      [&count](auto index, auto indexEnd) {\n        count.fetch_add(indexEnd - index, std::memory_order_relaxed);\n      });\n\n  EXPECT_EQ(count.load(), std::numeric_limits<uint16_t>::max());\n}\n\nTEST(GreedyForRanges, AvoidOverflow2) {\n  dispenso::ThreadPool pool(8);\n  dispenso::TaskSet taskSet(pool);\n  dispenso::ParForOptions options;\n  options.wait = false;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n\n  std::vector<dispenso::CacheAligned<uint32_t>> vals;\n  dispenso::parallel_for(\n      taskSet,\n      vals,\n      []() { return uint32_t{0}; },\n      std::numeric_limits<int32_t>::min() / 2 - 1,\n      std::numeric_limits<int32_t>::max() / 2 + 1,\n      [](auto& count, auto index, auto indexEnd) { count += indexEnd - index; },\n      options);\n  taskSet.wait();\n\n  uint32_t count = 0;\n  for (auto& v : vals) {\n    count += v;\n  }\n\n  EXPECT_EQ(count, std::numeric_limits<uint32_t>::max() / 2 + 2);\n}\n\nTEST(GreedyForRanges, EmptyLoopsWaitIfToldTo) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  std::atomic<int> count(0);\n\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      1000,\n      [&count](int index, int indexEnd) {\n        for (; index < indexEnd; ++index) {\n          std::this_thread::sleep_for(std::chrono::microseconds(1));\n          count.fetch_add(1, std::memory_order_acq_rel);\n        }\n      },\n      options);\n\n  dispenso::ParForOptions waitOptions;\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      0,\n      [](int /*index*/) { EXPECT_FALSE(true) << \"Should not reach this lambda\"; },\n      waitOptions);\n\n  EXPECT_EQ(count.load(), 1000);\n}\n\nTEST(GreedyForRanges, SingleLoopWaitIfToldTo) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  std::atomic<int> count(0);\n\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      1000,\n      [&count](int index, int indexEnd) {\n        for (; index < indexEnd; ++index) {\n          std::this_thread::sleep_for(std::chrono::microseconds(1));\n          count.fetch_add(1, std::memory_order_acq_rel);\n        }\n      },\n      options);\n\n  dispenso::ParForOptions waitOptions;\n  dispenso::parallel_for(taskSet, 0, 1, [](int i) { EXPECT_EQ(i, 0); }, waitOptions);\n\n  EXPECT_EQ(count.load(), 1000);\n}\n\nTEST(GreedyForRanges, ZeroThreads) {\n  // Using a threadpool with 0 threads should run via the calling thread.\n  dispenso::ThreadPool pool(0);\n  dispenso::TaskSet tasks(pool);\n\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::parallel_for(tasks, 0, h, [w, &image, &sum](int y, int yEnd) {\n    for (; y < yEnd; ++y) {\n      simpleInner(w, y, image, sum);\n    }\n  });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyForRanges, ZeroThreadsWithState) {\n  // Using a threadpool with 0 threads should run via the calling thread.\n  dispenso::ThreadPool pool(0);\n  loopWithStateImpl<std::vector<int64_t>>(pool);\n}\n"
  },
  {
    "path": "tests/greedy_for_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <list>\n#include <vector>\n\n#include <dispenso/parallel_for.h>\n\n#include <gtest/gtest.h>\n\n#include \"test_tid.h\"\n\nstatic void simpleInner(int w, int y, const std::vector<int>& image, std::atomic<int64_t>& sum) {\n  const int* row = image.data() + y * w;\n  int64_t s = 0;\n  for (int i = 0; i < w; ++i) {\n    s += row[i];\n  }\n  sum.fetch_add(s, std::memory_order_relaxed);\n}\n\nTEST(GreedyFor, SimpleLoop) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::parallel_for(0, h, [w, &image, &sum](int y) { simpleInner(w, y, image, sum); });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyFor, ShouldNotInvokeIfEmptyRange) {\n  int* myNullPtr = nullptr;\n\n  dispenso::ParForOptions options;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n\n  dispenso::parallel_for(0, 0, [myNullPtr](int i) { *myNullPtr = i; }, options);\n\n  options.defaultChunking = dispenso::ParForChunking::kStatic;\n\n  dispenso::parallel_for(0, 0, [myNullPtr](int i) { *myNullPtr = i; }, options);\n}\n\ntemplate <typename StateContainer>\nvoid loopWithStateImpl(dispenso::ThreadPool& pool = dispenso::globalThreadPool()) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  dispenso::TaskSet taskSet(pool);\n  StateContainer state;\n  dispenso::parallel_for(\n      taskSet,\n      state,\n      []() { return int64_t{0}; },\n      0,\n      h,\n      [w, &image](int64_t& sum, int y) {\n        int* row = image.data() + y * w;\n        int64_t s = 0;\n        for (int i = 0; i < w; ++i) {\n          s += row[i];\n        }\n        sum += s;\n      });\n\n  int64_t sum = 0;\n  for (int64_t s : state) {\n    sum += s;\n  }\n\n  EXPECT_EQ(sum, w * h * 7);\n}\n\nTEST(GreedyFor, LoopWithDequeState) {\n  loopWithStateImpl<std::deque<int64_t>>();\n}\nTEST(GreedyFor, LoopWithVectorState) {\n  loopWithStateImpl<std::vector<int64_t>>();\n}\nTEST(GreedyFor, LoopWithListState) {\n  loopWithStateImpl<std::list<int64_t>>();\n}\n\nTEST(GreedyFor, ConcurrentLoopNoCoordination) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  std::thread tA([w, h, &image, &sumA]() {\n    dispenso::parallel_for(0, h, [w, &image, &sumA](int y) { simpleInner(w, y, image, sumA); });\n  });\n  std::thread tB([w, h, &image, &sumB]() {\n    dispenso::parallel_for(0, h, [w, &image, &sumB](int y) { simpleInner(w, y, image, sumB); });\n  });\n\n  tA.join();\n  tB.join();\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyFor, CoordinatedLoops) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  dispenso::parallel_for(\n      taskSet, 0, h, [w, &image, &sumA](int y) { simpleInner(w, y, image, sumA); }, options);\n\n  dispenso::parallel_for(\n      taskSet, 0, h, [w, &image, &sumB](int y) { simpleInner(w, y, image, sumB); });\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nstatic void concurrentLoop(\n    dispenso::ConcurrentTaskSet& taskSet,\n    int w,\n    int h,\n    const std::vector<int>& image,\n    std::atomic<int64_t>& sum) {\n  dispenso::ParForOptions options;\n  options.wait = false;\n  dispenso::parallel_for(\n      taskSet, 0, h, [w, &image, &sum](int y) { simpleInner(w, y, image, sum); }, options);\n}\n\nTEST(GreedyFor, CoordinatedConcurrentLoops) {\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sumA(0);\n  std::atomic<int64_t> sumB(0);\n\n  dispenso::ConcurrentTaskSet taskSet(dispenso::globalThreadPool());\n\n  dispenso::ParForOptions options;\n  options.wait = false;\n  dispenso::parallel_for(\n      taskSet, 0, h, [w, &image, &sumA](int y) { simpleInner(w, y, image, sumA); }, options);\n\n  std::thread thread(\n      [&taskSet, w, h, &image, &sumB]() { concurrentLoop(taskSet, w, h, image, sumB); });\n  thread.join();\n  taskSet.wait();\n\n  EXPECT_EQ(sumA.load(std::memory_order_relaxed), w * h * 7);\n  EXPECT_EQ(sumB.load(std::memory_order_relaxed), w * h * 7);\n}\n\nstatic void\ntestMaxThreads(size_t poolSize, uint32_t maxThreads, bool testStaticChunking, bool testWaitOption) {\n  resetTestTid();\n  size_t numAvailableThreads = poolSize + testWaitOption;\n  std::vector<int> threadLocalSums(numAvailableThreads, 0);\n  dispenso::ThreadPool pool(poolSize);\n  dispenso::TaskSet tasks(pool);\n\n  dispenso::ParForOptions options;\n  options.maxThreads = maxThreads;\n  options.wait = testWaitOption;\n  options.defaultChunking =\n      testStaticChunking ? dispenso::ParForChunking::kStatic : dispenso::ParForChunking::kAuto;\n\n  auto func = [&threadLocalSums](int index) {\n    assert(index > 0); // for correctness of numNonZero\n    std::this_thread::yield();\n    threadLocalSums[getTestTid()] += index;\n  };\n\n  dispenso::parallel_for(tasks, 1, 10000, func, options);\n\n  if (!testWaitOption) {\n    // We didn't tell the parallel_for to wait, so we need to do it here to ensure the loop is\n    // complete.\n    tasks.wait();\n  }\n\n  int total = 0;\n  int numNonZero = 0;\n\n  for (size_t i = 0; i < numAvailableThreads; ++i) {\n    numNonZero += threadLocalSums[i] > 0;\n    total += threadLocalSums[i];\n  }\n\n  // 0 indicates serial execution per API spec\n  size_t translatedMaxThreads = maxThreads == 0 ? 1 : maxThreads;\n  EXPECT_LE(numNonZero, std::min((size_t)translatedMaxThreads, numAvailableThreads));\n  EXPECT_EQ(total, 49995000);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsBigPoolStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsBigPoolStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsBigPoolAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsBigPoolAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 4, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSmallPoolStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSmallPoolStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSmallPoolAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSmallPoolAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(4, 8, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSerialStaticChunkingBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSerialStaticChunkingNonBlocking) {\n  constexpr bool staticChunking = true;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSerialAutoChunkingBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = true;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, OptionsMaxThreadsSerialAutoChunkingNonBlocking) {\n  constexpr bool staticChunking = false;\n  constexpr bool waitOption = false;\n  testMaxThreads(8, 0, staticChunking, waitOption);\n}\n\nTEST(GreedyFor, NegativeRangeLength) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, 2, -2, [](auto /*index*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyFor, NegativeRangeLengthBig) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, 2147483647, -2147483647, [](auto /*index*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyFor, ZeroLength2) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(taskSet, -77, -77, [](auto /*index*/) {\n    EXPECT_FALSE(true) << \"Shouldn't enter this function at all\";\n  });\n}\n\nTEST(GreedyFor, AvoidOverflow1) {\n  std::atomic<uint32_t> count(0);\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::parallel_for(\n      taskSet,\n      std::numeric_limits<int16_t>::min(),\n      std::numeric_limits<int16_t>::max(),\n      [&count](auto /*index*/) { count.fetch_add(1, std::memory_order_relaxed); });\n\n  EXPECT_EQ(count.load(), std::numeric_limits<uint16_t>::max());\n}\n\nTEST(GreedyFor, AvoidOverflow2) {\n  dispenso::ThreadPool pool(8);\n  dispenso::TaskSet taskSet(pool);\n  dispenso::ParForOptions options;\n  options.wait = false;\n  options.defaultChunking = dispenso::ParForChunking::kAuto;\n\n  std::vector<dispenso::CacheAligned<uint32_t>> vals;\n  dispenso::parallel_for(\n      taskSet,\n      vals,\n      []() { return uint32_t{0}; },\n      std::numeric_limits<int32_t>::min() / 2 - 1,\n      std::numeric_limits<int32_t>::max() / 2 + 1,\n      [](auto& count, auto /*index*/) { ++count; },\n      options);\n  taskSet.wait();\n\n  uint32_t count = 0;\n  for (auto& v : vals) {\n    count += v;\n  }\n\n  EXPECT_EQ(count, std::numeric_limits<uint32_t>::max() / 2 + 2);\n}\n\nTEST(GreedyFor, EmptyLoopsWaitIfToldTo) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  std::atomic<int> count(0);\n\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      1000,\n      [&count](int /*index*/) {\n        std::this_thread::sleep_for(std::chrono::microseconds(1));\n        count.fetch_add(1, std::memory_order_acq_rel);\n      },\n      options);\n\n  dispenso::ParForOptions waitOptions;\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      0,\n      [](int /*index*/) { EXPECT_FALSE(true) << \"Should not reach this lambda\"; },\n      waitOptions);\n\n  EXPECT_EQ(count.load(), 1000);\n}\n\nTEST(GreedyFor, SingleLoopWaitIfToldTo) {\n  dispenso::TaskSet taskSet(dispenso::globalThreadPool());\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  std::atomic<int> count(0);\n\n  dispenso::parallel_for(\n      taskSet,\n      0,\n      1000,\n      [&count](int /*index*/) {\n        std::this_thread::sleep_for(std::chrono::microseconds(1));\n        count.fetch_add(1, std::memory_order_acq_rel);\n      },\n      options);\n\n  dispenso::ParForOptions waitOptions;\n  dispenso::parallel_for(taskSet, 0, 1, [](int i) { EXPECT_EQ(i, 0); }, waitOptions);\n\n  EXPECT_EQ(count.load(), 1000);\n}\n\nTEST(GreedyFor, ZeroThreads) {\n  // Using a threadpool with 0 threads should run via the calling thread.\n  dispenso::ThreadPool pool(0);\n  dispenso::TaskSet tasks(pool);\n\n  int w = 1000;\n  int h = 1000;\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::parallel_for(tasks, 0, h, [w, &image, &sum](int y) { simpleInner(w, y, image, sum); });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n\nTEST(GreedyFor, ZeroThreadsWithState) {\n  // Using a threadpool with 0 threads should run via the calling thread.\n  dispenso::ThreadPool pool(0);\n  loopWithStateImpl<std::vector<int64_t>>(pool);\n}\n\nTEST(GreedyFor, SimpleLoopFewerItemsThanThreads) {\n  int w = 1000;\n  int h = 3;\n  dispenso::ThreadPool pool(5);\n  std::vector<int> image(w * h, 7);\n\n  std::atomic<int64_t> sum(0);\n\n  dispenso::TaskSet tasks(pool);\n  dispenso::parallel_for(tasks, 0, h, [w, &image, &sum](int y) { simpleInner(w, y, image, sum); });\n\n  EXPECT_EQ(sum.load(std::memory_order_relaxed), w * h * 7);\n}\n"
  },
  {
    "path": "tests/latch_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <deque>\n#include <thread>\n\n#include <dispenso/latch.h>\n\n#include <gtest/gtest.h>\n\nusing namespace std::chrono_literals;\n\nTEST(Latch, ArriveAndWait) {\n  size_t publishData = 0;\n  dispenso::Latch latch(3);\n\n  std::deque<std::thread> threads;\n\n  for (size_t i = 0; i < 2; ++i) {\n    threads.emplace_back([&latch, &publishData]() {\n      latch.arrive_and_wait();\n      EXPECT_EQ(publishData, 3);\n    });\n  }\n\n  // Give plenty of time for hijinx if there were any bug.\n  std::this_thread::sleep_for(10ms);\n\n  publishData = 3;\n\n  // Wait cannot succeed until we also throw our hat in the ring, since we have 3 threads in the\n  // group, but only two threads waiting to check for a new value of publishData.  We do this\n  // after setting the value of publishData, from only one thread (main thread).  After\n  // arrive_and_wait, wait succeeds, and waiting threads are woken, and they should see the correct\n  // value of publishData.\n  latch.arrive_and_wait();\n\n  for (auto& t : threads) {\n    t.join();\n  }\n}\n\nTEST(Latch, CountDown) {\n  size_t publishData = 0;\n  dispenso::Latch latch(3);\n\n  std::deque<std::thread> threads;\n\n  for (size_t i = 0; i < 2; ++i) {\n    threads.emplace_back([&latch, &publishData]() {\n      latch.count_down();\n\n      if (latch.try_wait()) {\n        EXPECT_EQ(publishData, 3);\n      } else {\n        latch.wait();\n        EXPECT_EQ(publishData, 3);\n      }\n    });\n  }\n\n  publishData = 3;\n\n  // Wait cannot succeed until we also throw our hat in the ring, since we have 3 threads in the\n  // group, but only two threads waiting to check for a new value of publishData.  We do this\n  // after setting the value of publishData, from only one thread (main thread).  After count_down,\n  // wait succeeds, and waiting threads are woken, and they should see the correct value of\n  // publishData.\n  latch.count_down();\n\n  // Wait isn't required here.\n\n  for (auto& t : threads) {\n    t.join();\n  }\n}\n\nTEST(Latch, ArriveAndWaitWithCountDown) {\n  size_t publishData = 0;\n  dispenso::Latch latch(3);\n\n  std::deque<std::thread> threads;\n\n  for (size_t i = 0; i < 2; ++i) {\n    threads.emplace_back([&latch, &publishData]() {\n      latch.arrive_and_wait();\n      EXPECT_EQ(publishData, 3);\n    });\n  }\n\n  publishData = 3;\n\n  // Wait cannot succeed until we also throw our hat in the ring, since we have 3 threads in the\n  // group, but only two threads waiting to check for a new value of publishData.  We do this\n  // after setting the value of publishData, from only one thread (main thread).  After count_down,\n  // wait succeeds, and waiting threads are woken, and they should see the correct value of\n  // publishData.\n  latch.count_down();\n\n  // Wait isn't required here.\n\n  for (auto& t : threads) {\n    t.join();\n  }\n}\n"
  },
  {
    "path": "tests/once_function_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/once_function.h>\n\n#include <deque>\n\n#include <gtest/gtest.h>\n\nconstexpr size_t kExtraSmall = 8;\nconstexpr size_t kSmall = 24;\nconstexpr size_t kMedium = 120;\nconstexpr size_t kLarge = 248;\nconstexpr size_t kExtraLarge = 10000;\n\nusing dispenso::OnceFunction;\n\nTEST(OnceFunction, Empty) {\n  OnceFunction f([]() {});\n  f();\n}\n\nTEST(OnceFunction, MoveConstructor) {\n  OnceFunction f([]() {});\n  OnceFunction g(std::move(f));\n  g();\n}\n\nTEST(OnceFunction, MoveOperator) {\n  OnceFunction f([]() {});\n  OnceFunction g;\n  g = std::move(f);\n  g();\n}\n\ntemplate <size_t kSize>\nvoid testSize() {\n  constexpr size_t kNumElts = kSize - sizeof(int*);\n  struct Foo {\n    void operator()() {\n      int s = 0;\n      for (uint8_t b : buf) {\n        s += b;\n      }\n      *sum = s;\n    }\n    uint8_t buf[kNumElts];\n    int* sum;\n  } foo;\n  for (size_t i = 0; i < kNumElts; ++i) {\n    foo.buf[i] = static_cast<uint8_t>(i);\n  }\n  int answer;\n  foo.sum = &answer;\n  OnceFunction f(foo);\n  OnceFunction g(foo);\n  g();\n  f();\n  int expected = 0;\n  for (size_t i = 0; i < kNumElts; ++i) {\n    expected += static_cast<int>(i & 255);\n  }\n  EXPECT_EQ(answer, expected);\n}\n\ntemplate <>\nvoid testSize<8>() {\n  struct Foo {\n    void operator()() {\n      int s = 0;\n      *sum = s;\n    }\n    int* sum;\n  } foo;\n  int answer;\n  foo.sum = &answer;\n  OnceFunction f(foo);\n  OnceFunction g(foo);\n  g();\n  f();\n  int expected = 0;\n  EXPECT_EQ(answer, expected);\n}\n\nTEST(OnceFunction, ExtraSmall) {\n  testSize<kExtraSmall>();\n}\n\nTEST(OnceFunction, Small) {\n  testSize<kSmall>();\n}\n\nTEST(OnceFunction, Medium) {\n  testSize<kMedium>();\n}\n\nTEST(OnceFunction, Large) {\n  testSize<kLarge>();\n}\n\nTEST(OnceFunction, ExtraLarge) {\n  testSize<kExtraLarge>();\n}\n\nTEST(OnceFunction, MoveWithResult) {\n  int result = 5;\n  OnceFunction f([&result]() { result = 17; });\n  EXPECT_EQ(result, 5);\n  OnceFunction g(std::move(f));\n  EXPECT_EQ(result, 5);\n  g();\n  EXPECT_EQ(result, 17);\n}\n\ntemplate <size_t kNumElts>\nvoid ensureDestructor() {\n  int value = 0;\n  struct FooWithDestructor {\n    void operator()() {\n      ++*value;\n    }\n    ~FooWithDestructor() {\n      ++*value;\n    }\n    uint8_t buf[kNumElts];\n    int* value;\n  } foo;\n\n  foo.value = &value;\n\n  OnceFunction f(foo);\n  f();\n  EXPECT_EQ(value, 2);\n}\n\nTEST(OnceFunction, EnsureDestructionExtraSmall) {\n  ensureDestructor<kExtraSmall>();\n}\n\nTEST(OnceFunction, EnsureDestructionSmall) {\n  ensureDestructor<kSmall>();\n}\n\nTEST(OnceFunction, EnsureDestructionMedium) {\n  ensureDestructor<kMedium>();\n}\n\nTEST(OnceFunction, EnsureDestructionLarge) {\n  ensureDestructor<kLarge>();\n}\n\nTEST(OnceFunction, EnsureDestructionExtraLarge) {\n  ensureDestructor<kExtraLarge>();\n}\n\ntemplate <size_t alignment>\nstruct EnsureAlign {\n  void operator()() {\n    uintptr_t bloc = reinterpret_cast<uintptr_t>(&b);\n    EXPECT_EQ(0, bloc & (alignment - 1)) << \"broken for alignment: \" << alignment;\n  }\n\n  alignas(alignment) char b = 0;\n};\n\nTEST(OnceFunction, EnsureAlignment1) {\n  EnsureAlign<1> e;\n  OnceFunction f(e);\n  f();\n}\n\nTEST(OnceFunction, EnsureAlignment2) {\n  EnsureAlign<2> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment4) {\n  EnsureAlign<4> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment8) {\n  EnsureAlign<8> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment16) {\n  EnsureAlign<16> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment32) {\n  EnsureAlign<32> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment64) {\n  EnsureAlign<64> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment128) {\n  EnsureAlign<128> e;\n  OnceFunction f(e);\n  f();\n}\nTEST(OnceFunction, EnsureAlignment256) {\n  EnsureAlign<256> e;\n  OnceFunction f(e);\n  f();\n}\n"
  },
  {
    "path": "tests/pipeline_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/pipeline.h>\n\n#include <numeric>\n\n#include <gtest/gtest.h>\n\n#if __cplusplus >= 201703L\ntemplate <typename T>\nusing TestOptional = std::optional<T>;\n#else\ntemplate <typename T>\nusing TestOptional = dispenso::OpResult<T>;\n#endif // C++17\n\nTEST(Pipeline, SingleStageSerial) {\n  int counter = 0;\n\n  dispenso::pipeline([&counter]() {\n    if (counter++ < 10) {\n      return true;\n    }\n    return false;\n  });\n\n  EXPECT_EQ(counter, 11);\n}\n\nTEST(Pipeline, SingleStageSerialPassRefObject) {\n  int counter = 0;\n\n  auto single = [&counter]() {\n    if (counter++ < 10) {\n      return true;\n    }\n    return false;\n  };\n\n  dispenso::pipeline(single);\n\n  EXPECT_EQ(counter, 11);\n}\n\nTEST(Pipeline, MultiStageSerial) {\n  std::vector<int> inputs(10);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<int> sum(0);\n  dispenso::pipeline(\n      [&inputs, it = inputs.begin()]() mutable -> TestOptional<int> {\n        if (it != inputs.end()) {\n          return *it++;\n        }\n        return {};\n      },\n      [](auto num) -> TestOptional<int> {\n        if (num > 2 && num < 5) {\n          return {};\n        }\n        return num * num;\n      },\n      [](int num) { return num + 5; },\n      [&sum](auto num) { sum.fetch_add(num, std::memory_order_relaxed); });\n\n  int actualSum = 0;\n  for (int i = 0; i < 10; ++i) {\n    if (i <= 2 || i >= 5) {\n      actualSum += i * i + 5;\n    }\n  }\n\n  EXPECT_EQ(sum.load(std::memory_order_acquire), actualSum);\n}\n\n#if __cplusplus >= 201703L\n// This test is nearly identical to the one above, but ensures that we always are testing\n// dispenso::OpResult, because the rest of the tests use std::optional if we are in C++17 mode.\nTEST(Pipeline, MultiStageSerialOpResult) {\n  std::vector<int> inputs(10);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<int> sum(0);\n  dispenso::pipeline(\n      [&inputs, it = inputs.begin()]() mutable -> dispenso::OpResult<int> {\n        if (it != inputs.end()) {\n          return *it++;\n        }\n        return {};\n      },\n      [](auto num) -> dispenso::OpResult<int> {\n        if (num > 2 && num < 5) {\n          return {};\n        }\n        return num * num;\n      },\n      [](int num) { return num + 5; },\n      [&sum](auto num) { sum.fetch_add(num, std::memory_order_relaxed); });\n\n  int actualSum = 0;\n  for (int i = 0; i < 10; ++i) {\n    if (i <= 2 || i >= 5) {\n      actualSum += i * i + 5;\n    }\n  }\n\n  EXPECT_EQ(sum.load(std::memory_order_acquire), actualSum);\n}\n#endif // C++17\n\nTEST(Pipeline, SingleStageParallel) {\n  std::atomic<int> counter(0);\n\n  constexpr int kMaxConcurrency = 4;\n\n  dispenso::pipeline(\n      dispenso::stage(\n          [&counter]() {\n            if (counter.fetch_add(1, std::memory_order_acq_rel) < 10) {\n              return true;\n            }\n            return false;\n          },\n          kMaxConcurrency));\n\n  EXPECT_LE(counter.load(std::memory_order_acquire), 10 + kMaxConcurrency);\n}\n\nTEST(Pipeline, SingleStageParallelPassPrebuiltStage) {\n  std::atomic<int> counter(0);\n\n  constexpr int kMaxConcurrency = 4;\n\n  auto stage = dispenso::stage(\n      [&counter]() {\n        if (counter.fetch_add(1, std::memory_order_acq_rel) < 10) {\n          return true;\n        }\n        return false;\n      },\n      kMaxConcurrency);\n\n  dispenso::pipeline(stage);\n\n  EXPECT_LE(counter.load(std::memory_order_acquire), 10 + kMaxConcurrency);\n}\n\nTEST(Pipeline, MultiStageGenIsParallel) {\n  constexpr int kNumInputs = 1000;\n  std::vector<int> inputs(kNumInputs);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<int> sum(0);\n  std::atomic<size_t> counter(0);\n\n  dispenso::pipeline(\n      dispenso::stage(\n          [&counter, &inputs]() -> TestOptional<int> {\n            size_t cur = counter.fetch_add(1, std::memory_order_acq_rel);\n            if (cur < inputs.size()) {\n              return inputs[cur];\n            }\n            return {};\n          },\n          3),\n      [](auto num) -> TestOptional<int> {\n        if (num > 2 && num < 5) {\n          return {};\n        }\n        return num * num;\n      },\n      [](int num) { return num + 5; },\n      [&sum](auto num) { sum.fetch_add(num, std::memory_order_relaxed); });\n\n  int actualSum = 0;\n  for (int i = 0; i < kNumInputs; ++i) {\n    if (i <= 2 || i >= 5) {\n      actualSum += i * i + 5;\n    }\n  }\n\n  EXPECT_EQ(sum.load(std::memory_order_acquire), actualSum);\n}\n\nstruct Gen {\n  Gen(std::atomic<size_t>& c, std::vector<int>& i) : counter(c), inputs(i) {}\n  TestOptional<int*> operator()() {\n    size_t cur = counter.fetch_add(1, std::memory_order_acq_rel);\n    if (cur < inputs.size()) {\n      return &inputs[cur];\n    }\n    return {};\n  };\n\n  std::atomic<size_t>& counter;\n  std::vector<int>& inputs;\n};\n\nstruct Xform0 {\n  TestOptional<int*> operator()(int* n) {\n    int& num = *n;\n    if (num > 2 && num < 5) {\n      return {};\n    }\n    num *= num;\n    return n;\n  };\n};\n\nstruct Xform1 {\n  int* operator()(int* num) {\n    *num += 5;\n    return num;\n  }\n};\n\nstruct Sink {\n  void operator()(int* num) {\n    *num /= 2;\n  }\n};\n\nTEST(Pipeline, MultiStageCarryPointers) {\n  constexpr size_t kNumInputs = 1000;\n  std::vector<int> inputs(kNumInputs);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<size_t> counter(0);\n\n  Gen gen(counter, inputs);\n  Xform0 xform0;\n  Xform1 xform1;\n  Sink sink;\n  dispenso::pipeline(gen, xform0, xform1, sink);\n\n  for (size_t i = 0; i < kNumInputs; ++i) {\n    if (i <= 2 || i >= 5) {\n      EXPECT_EQ(inputs[i], ((i * i) + 5) / 2);\n    }\n  }\n}\n\nTEST(Pipeline, MultiStageCarryPointers2) {\n  constexpr size_t kNumInputs = 1000;\n  std::vector<int> inputs(kNumInputs);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<size_t> counter(0);\n\n  dispenso::pipeline(Gen(counter, inputs), Xform0(), Xform1(), Sink());\n\n  for (size_t i = 0; i < kNumInputs; ++i) {\n    if (i <= 2 || i >= 5) {\n      EXPECT_EQ(inputs[i], ((i * i) + 5) / 2);\n    }\n  }\n}\n\nTEST(Pipeline, MultiStageCarryPointersMultiFilterParallel) {\n  constexpr size_t kPar = 8;\n  constexpr size_t kNumInputs = 1000;\n  std::vector<int> inputs(kNumInputs);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<size_t> counter(0);\n\n  dispenso::pipeline(\n      dispenso::stage(Gen(counter, inputs), kPar),\n      dispenso::stage(Xform0(), kPar),\n      dispenso::stage(\n          [&inputs](int* in) -> TestOptional<int*> {\n            if (in - inputs.data() > 75 && in - inputs.data() < 80) {\n              return {};\n            }\n            return in;\n          },\n          kPar),\n      dispenso::stage(Xform1(), kPar),\n      dispenso::stage(Sink(), kPar));\n\n  for (size_t i = 0; i < kNumInputs; ++i) {\n    if (i > 2 && i < 5) {\n      EXPECT_EQ(inputs[i], i) << \" at index \" << i;\n    } else if (i > 75 && i < 80) {\n      EXPECT_EQ(inputs[i], i * i) << \" at index \" << i;\n    } else {\n      EXPECT_EQ(inputs[i], ((i * i) + 5) / 2) << \" at index \" << i;\n    }\n  }\n}\n\nTEST(Pipeline, MultiStageCarryPointersMultiFilterUnlimitedParallel) {\n  constexpr size_t kPar = dispenso::kStageNoLimit;\n  constexpr size_t kNumInputs = 1000;\n  std::vector<int> inputs(kNumInputs);\n  std::iota(inputs.begin(), inputs.end(), 0);\n  std::atomic<size_t> counter(0);\n\n  dispenso::pipeline(\n      dispenso::stage(Gen(counter, inputs), kPar),\n      dispenso::stage(Xform0(), kPar),\n      dispenso::stage(\n          [&inputs](int* in) -> TestOptional<int*> {\n            if (in - inputs.data() > 75 && in - inputs.data() < 80) {\n              return {};\n            }\n            return in;\n          },\n          kPar),\n      dispenso::stage(Xform1(), kPar),\n      dispenso::stage(Sink(), kPar));\n\n  for (size_t i = 0; i < kNumInputs; ++i) {\n    if (i > 2 && i < 5) {\n      EXPECT_EQ(inputs[i], i) << \" at index \" << i;\n    } else if (i > 75 && i < 80) {\n      EXPECT_EQ(inputs[i], i * i) << \" at index \" << i;\n    } else {\n      EXPECT_EQ(inputs[i], ((i * i) + 5) / 2) << \" at index \" << i;\n    }\n  }\n}\n\nstatic size_t g_count = 0;\n\nstatic TestOptional<size_t> funkGen() {\n  if (g_count < 10) {\n    return g_count++;\n  }\n  return {};\n}\n\nstatic std::atomic<size_t> g_sum(0);\nstatic void funkSink(size_t in) {\n  g_sum.fetch_add(in, std::memory_order_acq_rel);\n}\n\nTEST(Pipeline, PipelineFunctions) {\n  g_count = 0;\n  g_sum.store(0);\n\n  dispenso::pipeline(funkGen, funkSink);\n\n  EXPECT_EQ(45, g_sum.load(std::memory_order_acquire));\n}\n\nTEST(Pipeline, PipelineMoveOnly) {\n  std::atomic<size_t> sum(0);\n\n  dispenso::pipeline(\n      [counter = 0]() mutable -> TestOptional<std::unique_ptr<size_t>> {\n        if (counter < 10) {\n          return std::make_unique<size_t>(counter++);\n        }\n        return {};\n      },\n      [](std::unique_ptr<size_t> val) {\n        *val += 1;\n        return val;\n      },\n      [&sum](std::unique_ptr<size_t> val) { sum.fetch_add(*val); });\n\n  EXPECT_EQ(55, sum.load(std::memory_order_acquire));\n}\n\nTEST(Pipeline, PipelineMoveOnlyWithFiltering) {\n  std::atomic<size_t> sum(0);\n\n  dispenso::pipeline(\n      [counter = 0]() mutable -> TestOptional<std::unique_ptr<size_t>> {\n        if (counter < 10) {\n          return std::make_unique<size_t>(counter++);\n        }\n        return {};\n      },\n      [](std::unique_ptr<size_t> val) -> TestOptional<std::unique_ptr<size_t>> {\n        if (*val == 5) {\n          return {};\n        }\n        *val += 1;\n        return val;\n      },\n      [&sum](std::unique_ptr<size_t> val) { sum.fetch_add(*val); });\n\n  EXPECT_EQ(49, sum.load(std::memory_order_acquire));\n}\n\nTEST(Pipeline, ZeroSizeThreadPool) {\n  g_count = 0;\n  g_sum.store(0);\n\n  dispenso::ThreadPool pool(0);\n\n  dispenso::pipeline(pool, funkGen, funkSink);\n\n  EXPECT_EQ(45, g_sum.load(std::memory_order_acquire));\n}\n\nTEST(Pipeline, SerialStageStackBound) {\n  constexpr int kNumItems = 100000;\n  dispenso::ThreadPool pool(4);\n  std::atomic<int> processed{0};\n  dispenso::pipeline(\n      pool,\n      [n = 0, numItems = kNumItems]() mutable -> dispenso::OpResult<int> {\n        return n < numItems ? dispenso::OpResult<int>(n++) : dispenso::OpResult<int>();\n      },\n      [&](int) { processed.fetch_add(1, std::memory_order_relaxed); });\n  EXPECT_EQ(processed.load(), kNumItems);\n}\n\n#if defined(__cpp_exceptions)\n\n// Helper: run a throwing pipeline multiple times, then verify recovery by running\n// a non-throwing pipeline on the same pool and checking all items are processed.\ntemplate <typename PipelineFunc>\nvoid runExceptionSafetyTest(\n    dispenso::ThreadPool& pool,\n    int numItems,\n    int numRounds,\n    PipelineFunc&& throwingPipeline) {\n  for (int round = 0; round < numRounds; ++round) {\n    try {\n      throwingPipeline(pool, numItems);\n    } catch (...) {\n    }\n  }\n\n  // Recovery: run a clean pipeline on the same pool to verify it's still usable.\n  std::atomic<int> processed{0};\n  dispenso::pipeline(\n      pool,\n      [n = 0, numItems]() mutable -> dispenso::OpResult<int> {\n        return n < numItems ? dispenso::OpResult<int>(n++) : dispenso::OpResult<int>();\n      },\n      dispenso::stage([&](int) { processed.fetch_add(1, std::memory_order_relaxed); }, 1));\n  EXPECT_EQ(processed.load(), numItems);\n}\n\n// Sink stage throws (serial, limit=1)\nTEST(Pipeline, ExceptionSafety_SinkSerial) {\n  dispenso::ThreadPool pool(1);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage([](int) { throw std::runtime_error(\"sink\"); }, 1));\n  });\n}\n\n// Sink stage throws (parallel, limit=4)\nTEST(Pipeline, ExceptionSafety_SinkParallel) {\n  dispenso::ThreadPool pool(4);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage([](int) { throw std::runtime_error(\"sink_par\"); }, 4));\n  });\n}\n\n// Sink stage throws (unlimited)\nTEST(Pipeline, ExceptionSafety_SinkUnlimited) {\n  dispenso::ThreadPool pool(4);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage(\n            [](int) { throw std::runtime_error(\"sink_unlim\"); }, dispenso::kStageNoLimit));\n  });\n}\n\n// Transform stage throws (serial)\nTEST(Pipeline, ExceptionSafety_TransformSerial) {\n  dispenso::ThreadPool pool(2);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage([](int) -> int { throw std::runtime_error(\"transform\"); }, 1),\n        [](int) {});\n  });\n}\n\n// Transform stage throws (parallel)\nTEST(Pipeline, ExceptionSafety_TransformParallel) {\n  dispenso::ThreadPool pool(4);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage([](int) -> int { throw std::runtime_error(\"transform_par\"); }, 4),\n        [](int) {});\n  });\n}\n\n// Filtering (OpTransform) stage throws\nTEST(Pipeline, ExceptionSafety_OpTransform) {\n  dispenso::ThreadPool pool(2);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage(\n            [](int) -> dispenso::OpResult<int> { throw std::runtime_error(\"op_transform\"); }, 2),\n        [](int) {});\n  });\n}\n\n// Generator throws\nTEST(Pipeline, ExceptionSafety_Generator) {\n  dispenso::ThreadPool pool(2);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int) {\n    dispenso::pipeline(\n        p, []() -> dispenso::OpResult<int> { throw std::runtime_error(\"generator\"); }, [](int) {});\n  });\n}\n\n// SingleStage pipeline throws\nTEST(Pipeline, ExceptionSafety_SingleStage) {\n  dispenso::ThreadPool pool(1);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int) {\n    dispenso::pipeline(p, []() -> bool { throw std::runtime_error(\"single\"); });\n  });\n}\n\n// Multi-stage pipeline: middle transform throws\nTEST(Pipeline, ExceptionSafety_MultiStageMiddle) {\n  dispenso::ThreadPool pool(4);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        dispenso::stage([](int v) -> int { return v * 2; }, 2),\n        dispenso::stage([](int) -> int { throw std::runtime_error(\"middle\"); }, 2),\n        dispenso::stage([](int v) -> int { return v + 1; }, 2),\n        [](int) {});\n  });\n}\n\n// Sink throws with unrelated function as generator (no stage wrapper)\nTEST(Pipeline, ExceptionSafety_PlainFunctionSink) {\n  dispenso::ThreadPool pool(2);\n  runExceptionSafetyTest(pool, 50, 40, [](auto& p, int n) {\n    dispenso::pipeline(\n        p,\n        [n, i = 0]() mutable -> dispenso::OpResult<int> {\n          return i < n ? dispenso::OpResult<int>(i++) : dispenso::OpResult<int>();\n        },\n        [](int) { throw std::runtime_error(\"plain_sink\"); });\n  });\n}\n\n#endif // __cpp_exceptions\n"
  },
  {
    "path": "tests/pool_allocator_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/pool_allocator.h>\n\n#include <deque>\n\n#include <gtest/gtest.h>\n\nTEST(PoolAllocator, SimpleMallocFree) {\n  dispenso::PoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  char* buf = allocator.alloc();\n\n  *buf = 'a';\n\n  allocator.dealloc(buf);\n}\n\nTEST(PoolAllocator, TrackAllocations) {\n  std::map<char*, size_t> allocMap;\n\n  auto allocFunc = [&allocMap](size_t len) -> void* {\n    char* ret = reinterpret_cast<char*>(::malloc(len));\n    allocMap.emplace(ret, len);\n    return ret;\n  };\n\n  auto deallocFunc = [&allocMap](void* ptr) {\n    EXPECT_EQ(1, allocMap.erase(reinterpret_cast<char*>(ptr)));\n    ::free(ptr);\n  };\n\n  // Check to make sure that the ptr returned by the allocator below is in one of the buffers\n  // generated by allocFunc.  We do this by examining the closest buffer (via lower_bound) in the\n  // map, and then verify that that buffer contains ptr.\n  auto checkInValidRange = [&allocMap](char* ptr) {\n    auto it = allocMap.upper_bound(ptr);\n    --it;\n    EXPECT_GE(ptr, it->first);\n    EXPECT_LT(ptr, it->first + it->second);\n    return ptr;\n  };\n\n  {\n    dispenso::PoolAllocator allocator(64, 256, allocFunc, deallocFunc);\n\n    char* bufs[5];\n\n    bufs[0] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(1, allocMap.size());\n\n    bufs[1] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(1, allocMap.size());\n\n    allocator.dealloc(bufs[0]);\n\n    EXPECT_EQ(1, allocMap.size());\n\n    bufs[0] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(1, allocMap.size());\n\n    bufs[2] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(1, allocMap.size());\n\n    bufs[3] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(1, allocMap.size());\n\n    bufs[4] = checkInValidRange(allocator.alloc());\n\n    EXPECT_EQ(2, allocMap.size());\n\n    allocator.dealloc(bufs[4]);\n    EXPECT_LE(2, allocMap.size());\n  }\n\n  EXPECT_EQ(allocMap.size(), 0);\n}\n\nTEST(PoolAllocator, SimpleThreaded) {\n  constexpr size_t kNumThreads = 8;\n\n  dispenso::PoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  std::deque<std::thread> threads;\n\n  for (size_t i = 0; i < kNumThreads; ++i) {\n    threads.emplace_back([&allocator, tid = i]() {\n      constexpr size_t kNumBufs = 8;\n      char* bufs[kNumBufs];\n\n      for (size_t i = 0; i < 1000; ++i) {\n        for (size_t j = 0; j < kNumBufs; ++j) {\n          bufs[j] = allocator.alloc();\n          *bufs[j] = static_cast<char>(tid);\n        }\n        for (size_t j = 0; j < kNumBufs; ++j) {\n          EXPECT_EQ(*bufs[j], tid);\n          allocator.dealloc(bufs[j]);\n        }\n      }\n    });\n  }\n\n  for (auto& t : threads) {\n    t.join();\n  }\n}\n\nTEST(PoolAllocator, Arena) {\n  dispenso::PoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  std::vector<char*> vec(2000);\n  for (char*& c : vec) {\n    c = allocator.alloc();\n    std::fill_n(c, 64, 0x7f);\n  }\n\n  for (char* c : vec) {\n    EXPECT_TRUE(std::all_of(c, c + 64, [](char v) { return v == 0x7f; }));\n  }\n\n  allocator.clear();\n  vec.resize(128);\n  for (char*& c : vec) {\n    c = allocator.alloc();\n    std::fill_n(c, 64, 0x22);\n  }\n\n  for (char* c : vec) {\n    EXPECT_TRUE(std::all_of(c, c + 64, [](char v) { return v == 0x22; }));\n  }\n\n  allocator.clear();\n  vec.resize(48);\n  for (char*& c : vec) {\n    c = allocator.alloc();\n    std::fill_n(c, 64, 0x11);\n  }\n\n  for (char* c : vec) {\n    EXPECT_TRUE(std::all_of(c, c + 64, [](char v) { return v == 0x11; }));\n  }\n}\n\nTEST(NoLockPoolAllocator, SimpleMallocFree) {\n  // Test the non-thread-safe version\n  dispenso::NoLockPoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  char* buf = allocator.alloc();\n  *buf = 'a';\n  allocator.dealloc(buf);\n}\n\nTEST(NoLockPoolAllocator, MultipleAllocDealloc) {\n  dispenso::NoLockPoolAllocator allocator(32, 128, ::malloc, ::free);\n\n  // Allocate several chunks\n  std::vector<char*> bufs;\n  for (int i = 0; i < 10; ++i) {\n    char* buf = allocator.alloc();\n    std::fill_n(buf, 32, static_cast<char>(i));\n    bufs.push_back(buf);\n  }\n\n  // Verify contents\n  for (int i = 0; i < 10; ++i) {\n    EXPECT_TRUE(\n        std::all_of(bufs[static_cast<size_t>(i)], bufs[static_cast<size_t>(i)] + 32, [i](char v) {\n          return v == static_cast<char>(i);\n        }));\n  }\n\n  // Dealloc all\n  for (char* buf : bufs) {\n    allocator.dealloc(buf);\n  }\n}\n\nTEST(PoolAllocator, TotalChunkCapacity) {\n  size_t allocCount = 0;\n  auto allocFunc = [&allocCount](size_t len) -> void* {\n    ++allocCount;\n    return ::malloc(len);\n  };\n\n  dispenso::PoolAllocator allocator(64, 256, allocFunc, ::free);\n\n  // Initially no backing allocations\n  EXPECT_EQ(allocator.totalChunkCapacity(), 0u);\n\n  // First alloc triggers a backing allocation\n  char* buf1 = allocator.alloc();\n  EXPECT_EQ(allocCount, 1u);\n  EXPECT_EQ(allocator.totalChunkCapacity(), 4u); // 256 / 64 = 4 chunks\n\n  // Allocate remaining chunks in first slab\n  char* buf2 = allocator.alloc();\n  char* buf3 = allocator.alloc();\n  char* buf4 = allocator.alloc();\n  EXPECT_EQ(allocCount, 1u); // Still just 1 backing allocation\n  EXPECT_EQ(allocator.totalChunkCapacity(), 4u);\n\n  // Next alloc triggers another backing allocation\n  char* buf5 = allocator.alloc();\n  EXPECT_EQ(allocCount, 2u);\n  EXPECT_EQ(allocator.totalChunkCapacity(), 8u); // 2 slabs * 4 chunks\n\n  allocator.dealloc(buf1);\n  allocator.dealloc(buf2);\n  allocator.dealloc(buf3);\n  allocator.dealloc(buf4);\n  allocator.dealloc(buf5);\n}\n\nTEST(PoolAllocator, SingleChunkPerSlab) {\n  // Edge case: chunkSize equals allocSize, so only 1 chunk per slab\n  size_t allocCount = 0;\n  auto allocFunc = [&allocCount](size_t len) -> void* {\n    ++allocCount;\n    return ::malloc(len);\n  };\n\n  dispenso::PoolAllocator allocator(128, 128, allocFunc, ::free);\n\n  EXPECT_EQ(allocator.totalChunkCapacity(), 0u);\n\n  char* buf1 = allocator.alloc();\n  EXPECT_EQ(allocCount, 1u);\n  EXPECT_EQ(allocator.totalChunkCapacity(), 1u);\n\n  char* buf2 = allocator.alloc();\n  EXPECT_EQ(allocCount, 2u);\n  EXPECT_EQ(allocator.totalChunkCapacity(), 2u);\n\n  allocator.dealloc(buf1);\n  allocator.dealloc(buf2);\n}\n\nTEST(PoolAllocator, ClearEmptyAllocator) {\n  // Edge case: calling clear() when nothing has been allocated\n  dispenso::PoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  // Should not crash\n  allocator.clear();\n  allocator.clear();\n\n  // Can still allocate after clear\n  char* buf = allocator.alloc();\n  *buf = 'x';\n  EXPECT_EQ(*buf, 'x');\n  allocator.dealloc(buf);\n}\n\nTEST(PoolAllocator, MultipleClearCycles) {\n  size_t allocCount = 0;\n  size_t deallocCount = 0;\n\n  auto allocFunc = [&allocCount](size_t len) -> void* {\n    ++allocCount;\n    return ::malloc(len);\n  };\n\n  auto deallocFunc = [&deallocCount](void* ptr) {\n    ++deallocCount;\n    ::free(ptr);\n  };\n\n  {\n    dispenso::PoolAllocator allocator(64, 256, allocFunc, deallocFunc);\n\n    // First cycle\n    std::vector<char*> bufs;\n    for (int i = 0; i < 20; ++i) {\n      bufs.push_back(allocator.alloc());\n    }\n    size_t firstCycleAllocs = allocCount;\n    EXPECT_GT(firstCycleAllocs, 0u);\n\n    allocator.clear();\n    EXPECT_EQ(deallocCount, 0u); // clear() doesn't deallocate\n\n    // Second cycle - should reuse backing allocations\n    bufs.clear();\n    for (int i = 0; i < 10; ++i) {\n      bufs.push_back(allocator.alloc());\n    }\n    EXPECT_EQ(allocCount, firstCycleAllocs); // No new backing allocations\n\n    allocator.clear();\n\n    // Third cycle\n    bufs.clear();\n    for (int i = 0; i < 5; ++i) {\n      bufs.push_back(allocator.alloc());\n    }\n    EXPECT_EQ(allocCount, firstCycleAllocs); // Still no new backing allocations\n  }\n\n  // Destructor deallocates all backing allocations\n  EXPECT_EQ(deallocCount, allocCount);\n}\n\nTEST(PoolAllocator, ReuseAfterDealloc) {\n  // Verify that deallocated chunks are reused\n  dispenso::PoolAllocator allocator(64, 256, ::malloc, ::free);\n\n  char* buf1 = allocator.alloc();\n  std::fill_n(buf1, 64, 'A');\n\n  allocator.dealloc(buf1);\n\n  // Next alloc should return the same chunk (LIFO behavior)\n  char* buf2 = allocator.alloc();\n  EXPECT_EQ(buf1, buf2);\n\n  // Contents may have been overwritten, but that's expected\n  allocator.dealloc(buf2);\n}\n"
  },
  {
    "path": "tests/priority_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <chrono>\n#include <cmath>\n\n#include <dispenso/completion_event.h>\n#include <dispenso/latch.h>\n#include <dispenso/parallel_for.h>\n#include <dispenso/priority.h>\n#include <dispenso/timing.h>\n\n#include <gtest/gtest.h>\n\n// NOTE: This isn't suitable for an automated unit test for multiple reasons.  With OS\n// scheduling we have some amount of nondeterminism.  Additionally, many (most?) machines will not\n// have permissions for kHigh and kRealtime priorities depending on OS and policies.\n//\n//  On Linux, with permissions appropriate, this test passes about 14/15 times.  On the single\n//  failure, I see an average sleep error like this:\n// Expected: (info[2].error()) >= (info[3].error()), actual: 5.25784e-05 vs 5.41972e-05\n// or about 50ish microseconds average error for both kHigh and kRealtime priorities.\n\nusing namespace std::chrono_literals;\n\nstruct ThreadInfo {\n  uint64_t count = 0;\n  double sleepErrorSum = 0.0;\n  bool prioOk = false;\n\n  double error() const {\n    return sleepErrorSum / static_cast<double>(count);\n  }\n};\n\nvoid run(\n    size_t index,\n    ThreadInfo& info,\n    dispenso::CompletionEvent& notifier,\n    dispenso::Latch& started) {\n  switch (index) {\n    case 0:\n      info.prioOk = dispenso::setCurrentThreadPriority(dispenso::ThreadPriority::kLow);\n      break;\n    case 1:\n      info.prioOk = dispenso::setCurrentThreadPriority(dispenso::ThreadPriority::kNormal);\n      break;\n    case 2:\n      info.prioOk = dispenso::setCurrentThreadPriority(dispenso::ThreadPriority::kHigh);\n      break;\n    case 3:\n      info.prioOk = dispenso::setCurrentThreadPriority(dispenso::ThreadPriority::kRealtime);\n      break;\n    default:\n      info.prioOk = true;\n      break;\n  }\n\n  // Ensure all threads reach this point before we begin, so that we don't let the first threads\n  // make progress before the system is bogged down.\n  started.arrive_and_wait();\n\n  // Keep other threads busy.  If cores are idle, the result will be a crapshoot.\n  if (index > 3) {\n    while (!notifier.completed()) {\n      ++info.count;\n#if defined(DISPENSO_HAS_TSAN)\n      // In TSAN atomics are implemented via reader/writer locks, and I believe these are not\n      // guaranteeing progress.  We need to take some time out from the tight loop calling\n      // notifier.completed() in order to allow the atomic write to succeed.\n      std::this_thread::yield();\n#endif // TSAN\n    }\n    return;\n  }\n\n  while (true) {\n    double start = dispenso::getTime();\n    if (!notifier.waitFor(1ms)) {\n      double end = dispenso::getTime();\n      ++info.count;\n      info.sleepErrorSum += std::abs((end - start) - 1e-3);\n    } else {\n      break;\n    }\n  }\n}\n\nTEST(Priorty, PriorityGetsCycles) {\n  dispenso::ParForOptions options;\n  options.wait = false;\n\n  int overloadConcurrency = 2 * std::thread::hardware_concurrency();\n\n  if (sizeof(void*) == 4) {\n    overloadConcurrency = std::min(overloadConcurrency, 62);\n  }\n\n  dispenso::ThreadPool pool(std::max<dispenso::ssize_t>(10, overloadConcurrency));\n\n  std::vector<ThreadInfo> info(pool.numThreads());\n\n  dispenso::CompletionEvent stop;\n  dispenso::Latch started(static_cast<uint32_t>(pool.numThreads()));\n\n  dispenso::TaskSet tasks(pool);\n  dispenso::parallel_for(\n      tasks,\n      0,\n      pool.numThreads(),\n      [&info, &stop, &started](size_t index) { run(index, info[index], stop, started); },\n      options);\n\n  // Let threads wake about 5000 times.\n  std::this_thread::sleep_for(5s);\n\n  stop.notify();\n\n  tasks.wait();\n\n  for (auto& i : info) {\n    EXPECT_TRUE(i.prioOk) << \"Failed for \" << &i - info.data();\n  }\n\n#if !defined(DISPENSO_HAS_TSAN)\n  // TSAN messes with scheduling enough that all bets are off.\n  EXPECT_GE(info[0].error(), info[1].error());\n  EXPECT_GE(info[1].error(), info[2].error());\n  EXPECT_GE(info[2].error(), info[3].error());\n#endif // TSAN\n}\n"
  },
  {
    "path": "tests/resource_pool_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <gtest/gtest.h>\n\n#include <dispenso/resource_pool.h>\n#include <dispenso/thread_pool.h>\n\nnamespace {\n// In real use cases, the buffer may perform some expensive initialization such as allocate a large\n// chunk of memory.\nstruct Buffer {\n  Buffer(std::atomic_int& _total_count, std::atomic_int& _num_buffers)\n      : total_count(_total_count), num_buffers(_num_buffers), count(0) {}\n  // On destruction, add the count\n  ~Buffer() {\n    total_count += count;\n    num_buffers += 1;\n  }\n  std::atomic_int& total_count;\n  std::atomic_int& num_buffers;\n  int count;\n};\n\nvoid BuffersTest(const int num_threads, const int num_buffers) {\n  constexpr int kNumTasks = 100000;\n  std::atomic_int total_count(0);\n  std::atomic_int num_buffers_created(0);\n  {\n    dispenso::ResourcePool<Buffer> buffer_pool(num_buffers, [&total_count, &num_buffers_created]() {\n      return Buffer(total_count, num_buffers_created);\n    });\n    dispenso::ThreadPool thread_pool(num_threads);\n    for (int i = 0; i < kNumTasks; ++i) {\n      thread_pool.schedule([&]() {\n        auto buffer_resource = buffer_pool.acquire();\n        ++buffer_resource.get().count;\n      });\n    }\n  }\n\n  // The sum of all the buffers counts should be equal to the number of tasks.\n  EXPECT_EQ(total_count, kNumTasks);\n  EXPECT_EQ(num_buffers_created, num_buffers);\n}\n\n} // namespace\n\nTEST(ResourcePool, SameNumBuffersAsThreadsTest) {\n  constexpr int kNumBuffers = 2;\n  constexpr int kNumThreads = 2;\n  BuffersTest(kNumBuffers, kNumThreads);\n}\n\nTEST(ResourcePool, FewerBuffersThanThreadsTest) {\n  constexpr int kNumBuffers = 1;\n  constexpr int kNumThreads = 2;\n  BuffersTest(kNumBuffers, kNumThreads);\n}\n\nTEST(ResourcePool, MoreBuffersThanThreadsTest) {\n  constexpr int kNumBuffers = 2;\n  constexpr int kNumThreads = 1;\n  BuffersTest(kNumBuffers, kNumThreads);\n}\n"
  },
  {
    "path": "tests/rw_lock_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/rw_lock.h>\n\n#include <chrono>\n#include <mutex>\n#include <shared_mutex>\n#include <thread>\n\n#include <gtest/gtest.h>\n\nusing namespace std::chrono_literals;\n\nTEST(RWLock, SimpleUncontested) {\n  dispenso::RWLock mtx;\n  int foo = 0;\n  std::unique_lock<dispenso::RWLock> lk(mtx);\n  foo = 1;\n\n  lk.unlock();\n\n  EXPECT_EQ(foo, 1);\n}\n\nTEST(RWLock, BasicWriterTest) {\n  int count = 0;\n  dispenso::RWLock mtx;\n  constexpr int kPerThreadTotal = 100000;\n\n  auto toRun = [&]() {\n    for (int i = 0; i < kPerThreadTotal; ++i) {\n      std::unique_lock<dispenso::RWLock> lk(mtx);\n      ++count;\n    }\n  };\n\n  std::thread thread0(toRun);\n  std::thread thread1(toRun);\n\n  thread0.join();\n  thread1.join();\n\n  EXPECT_EQ(count, 2 * kPerThreadTotal);\n}\n\nTEST(RWLock, HighContentionReaderWriterTest) {\n  int count = 0;\n  dispenso::RWLock mtx;\n  constexpr int kPerThreadTotal = 100000;\n\n  auto toRunWriter = [&]() {\n    for (int i = 0; i < kPerThreadTotal; ++i) {\n      std::unique_lock<dispenso::RWLock> lk(mtx);\n      ++count;\n    }\n  };\n\n  int64_t someVal = 0;\n\n  auto toRunReader = [&]() {\n    for (int i = 0; i < kPerThreadTotal; ++i) {\n      std::shared_lock<dispenso::RWLock> lk(mtx);\n      someVal += count;\n    }\n  };\n\n  std::thread thread0(toRunWriter);\n  std::thread thread1(toRunReader);\n\n  thread0.join();\n  thread1.join();\n\n  EXPECT_EQ(count, kPerThreadTotal);\n  EXPECT_GE(someVal, 0);\n}\n\nTEST(RWLock, ReaderWriterTest) {\n  int guardedCount = 0;\n  dispenso::RWLock mtx;\n  constexpr int kWriterTotal = 100;\n  constexpr int kReaderTotal = 100000;\n\n  auto toRunWriter = [&]() {\n    for (int i = 0; i < kWriterTotal; ++i) {\n      std::unique_lock<dispenso::RWLock> lk(mtx);\n      ++guardedCount;\n      lk.unlock();\n      // Just hang out for a while til we write again.\n      std::this_thread::sleep_for(1ms);\n    }\n  };\n\n  int64_t sum = 0;\n\n  auto toRunReader = [&]() {\n    for (int i = 0; i < kReaderTotal; ++i) {\n      std::shared_lock<dispenso::RWLock> lk(mtx);\n      sum += guardedCount;\n    }\n  };\n\n  std::thread thread0(toRunWriter);\n  std::thread thread1(toRunReader);\n\n  thread0.join();\n  thread1.join();\n\n  EXPECT_EQ(guardedCount, kWriterTotal);\n  EXPECT_GE(sum, 0);\n}\n\nTEST(RWLock, TestAlignment) {\n  static_assert(\n      alignof(dispenso::RWLock) >= dispenso::kCacheLineSize,\n      \"Somehow RWLock not aligned to avoid false sharing\");\n  static_assert(\n      alignof(dispenso::UnalignedRWLock) < dispenso::kCacheLineSize,\n      \"UnalignedRWLock is overaligned\");\n}\n"
  },
  {
    "path": "tests/shared_pool_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#ifdef _WIN32\n__declspec(dllimport) void* sharedPoolA();\n__declspec(dllimport) void* sharedPoolB();\n#else\n__attribute__((visibility(\"default\"))) void* sharedPoolA();\n__attribute__((visibility(\"default\"))) void* sharedPoolB();\n#endif\n\nTEST(ThreadPool, SharedPool) {\n  EXPECT_EQ(sharedPoolA(), sharedPoolB());\n}\n"
  },
  {
    "path": "tests/small_buffer_allocator_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/small_buffer_allocator.h>\n\n#include <thread>\n#include <vector>\n\n#include <gtest/gtest.h>\n\n// Helper to test alloc/dealloc for a specific size\ntemplate <size_t kSize>\nvoid testAllocDealloc() {\n  char* buf = dispenso::allocSmallBuffer<kSize>();\n  ASSERT_NE(buf, nullptr);\n  // Write to first and last byte to verify usability\n  buf[0] = 'a';\n  buf[kSize - 1] = 'z';\n  dispenso::deallocSmallBuffer<kSize>(buf);\n}\n\n// Test allocation and deallocation for various sizes from 1 to 1024\n// Note: The allocator supports sizes 4-256 in pools (smaller sizes map to 4-byte blocks),\n// larger sizes use alignedMalloc\nTEST(SmallBufferAllocator, AllocDeallocVariousSizes) {\n  testAllocDealloc<1>(); // Maps to 4-byte block\n  testAllocDealloc<2>(); // Maps to 4-byte block\n  testAllocDealloc<3>(); // Maps to 4-byte block (non-power-of-2)\n  testAllocDealloc<4>();\n  testAllocDealloc<8>();\n  testAllocDealloc<16>();\n  testAllocDealloc<32>();\n  testAllocDealloc<64>();\n  testAllocDealloc<128>();\n  testAllocDealloc<256>();\n  testAllocDealloc<512>();\n  testAllocDealloc<1024>();\n}\n\n// Helper to test bytesAllocated for a specific size\ntemplate <\n    size_t kSize,\n    typename std::enable_if<(kSize <= dispenso::kMaxSmallBufferSize), int>::type = 0>\nvoid testBytesAllocated() {\n  char* buf = dispenso::allocSmallBuffer<kSize>();\n  EXPECT_GT(dispenso::approxBytesAllocatedSmallBuffer<kSize>(), size_t{0});\n  dispenso::deallocSmallBuffer<kSize>(buf);\n}\n\n// Overload for sizes > kMaxSmallBufferSize (no-op since they use aligned malloc)\ntemplate <\n    size_t kSize,\n    typename std::enable_if<(kSize > dispenso::kMaxSmallBufferSize), int>::type = 0>\nvoid testBytesAllocated() {\n  // Sizes larger than kMaxSmallBufferSize fall back to aligned malloc\n  // and don't track bytes in the pool, so nothing to test\n}\n\n// Test bytesAllocated for various sizes\nTEST(SmallBufferAllocator, BytesAllocatedVariousSizes) {\n  testBytesAllocated<4>();\n  testBytesAllocated<8>();\n  testBytesAllocated<16>();\n  testBytesAllocated<32>();\n  testBytesAllocated<64>();\n  testBytesAllocated<128>();\n  testBytesAllocated<256>();\n}\n\n// Test multiple allocations of same size\ntemplate <size_t kSize>\nvoid testMultipleAllocs() {\n  constexpr size_t kNumAllocs = 100;\n  std::vector<char*> buffers(kNumAllocs);\n\n  // Allocate many buffers\n  for (size_t i = 0; i < kNumAllocs; ++i) {\n    buffers[i] = dispenso::allocSmallBuffer<kSize>();\n    ASSERT_NE(buffers[i], nullptr);\n    // Write a pattern to verify no overlap\n    buffers[i][0] = static_cast<char>(i & 0xFF);\n  }\n\n  // Verify patterns\n  for (size_t i = 0; i < kNumAllocs; ++i) {\n    EXPECT_EQ(buffers[i][0], static_cast<char>(i & 0xFF));\n  }\n\n  // Deallocate all\n  for (size_t i = 0; i < kNumAllocs; ++i) {\n    dispenso::deallocSmallBuffer<kSize>(buffers[i]);\n  }\n}\n\nTEST(SmallBufferAllocator, MultipleAllocsSmallSize) {\n  testMultipleAllocs<16>();\n}\n\nTEST(SmallBufferAllocator, MultipleAllocsMediumSize) {\n  testMultipleAllocs<64>();\n}\n\nTEST(SmallBufferAllocator, MultipleAllocsLargeSize) {\n  testMultipleAllocs<256>();\n}\n\nTEST(SmallBufferAllocator, MultipleAllocsOverMaxSize) {\n  testMultipleAllocs<512>();\n}\n\n// Test allocation reuse after deallocation\nTEST(SmallBufferAllocator, AllocationReuse) {\n  // Allocate and deallocate, then allocate again\n  char* buf1 = dispenso::allocSmallBuffer<32>();\n  ASSERT_NE(buf1, nullptr);\n  dispenso::deallocSmallBuffer<32>(buf1);\n\n  char* buf2 = dispenso::allocSmallBuffer<32>();\n  ASSERT_NE(buf2, nullptr);\n  dispenso::deallocSmallBuffer<32>(buf2);\n}\n\n// Test threaded allocation/deallocation with various sizes\nTEST(SmallBufferAllocator, ThreadedAllocDealloc) {\n  constexpr size_t kNumThreads = 8;\n  constexpr size_t kNumAllocsPerThread = 500;\n\n  auto threadFunc = [&](size_t threadId) {\n    for (size_t i = 0; i < kNumAllocsPerThread; ++i) {\n      // Rotate through different sizes\n      switch ((threadId + i) % 5) {\n        case 0: {\n          char* buf = dispenso::allocSmallBuffer<8>();\n          buf[0] = 'x';\n          dispenso::deallocSmallBuffer<8>(buf);\n          break;\n        }\n        case 1: {\n          char* buf = dispenso::allocSmallBuffer<32>();\n          buf[0] = 'x';\n          dispenso::deallocSmallBuffer<32>(buf);\n          break;\n        }\n        case 2: {\n          char* buf = dispenso::allocSmallBuffer<64>();\n          buf[0] = 'x';\n          dispenso::deallocSmallBuffer<64>(buf);\n          break;\n        }\n        case 3: {\n          char* buf = dispenso::allocSmallBuffer<128>();\n          buf[0] = 'x';\n          dispenso::deallocSmallBuffer<128>(buf);\n          break;\n        }\n        case 4: {\n          char* buf = dispenso::allocSmallBuffer<256>();\n          buf[0] = 'x';\n          dispenso::deallocSmallBuffer<256>(buf);\n          break;\n        }\n      }\n    }\n  };\n\n  std::vector<std::thread> threads;\n  for (size_t t = 0; t < kNumThreads; ++t) {\n    threads.emplace_back(threadFunc, t);\n  }\n\n  for (auto& t : threads) {\n    t.join();\n  }\n}\n"
  },
  {
    "path": "tests/small_vector_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/small_vector.h>\n\n#include <string>\n#include <utility>\n\n#include <gtest/gtest.h>\n\nusing dispenso::SmallVector;\n\n// Test helper to track construction/destruction\nstruct Tracked {\n  static int constructed;\n  static int destructed;\n  static int moveConstructed;\n  static int copyConstructed;\n\n  static void reset() {\n    constructed = 0;\n    destructed = 0;\n    moveConstructed = 0;\n    copyConstructed = 0;\n  }\n\n  int value;\n\n  Tracked() : value(0) {\n    ++constructed;\n  }\n  explicit Tracked(int v) : value(v) {\n    ++constructed;\n  }\n  Tracked(const Tracked& other) : value(other.value) {\n    ++constructed;\n    ++copyConstructed;\n  }\n  Tracked(Tracked&& other) noexcept : value(other.value) {\n    other.value = -1;\n    ++constructed;\n    ++moveConstructed;\n  }\n  ~Tracked() {\n    ++destructed;\n  }\n  Tracked& operator=(const Tracked& other) {\n    value = other.value;\n    return *this;\n  }\n  Tracked& operator=(Tracked&& other) noexcept {\n    value = other.value;\n    other.value = -1;\n    return *this;\n  }\n};\n\nint Tracked::constructed = 0;\nint Tracked::destructed = 0;\nint Tracked::moveConstructed = 0;\nint Tracked::copyConstructed = 0;\n\n// --- Construction Tests ---\n\nTEST(SmallVector, DefaultConstruction) {\n  SmallVector<int> v;\n  EXPECT_TRUE(v.empty());\n  EXPECT_EQ(v.size(), 0u);\n  EXPECT_GE(v.capacity(), 4u);\n}\n\nTEST(SmallVector, ConstructionWithSize) {\n  SmallVector<int> v(3);\n  EXPECT_EQ(v.size(), 3u);\n  for (size_t i = 0; i < v.size(); ++i) {\n    EXPECT_EQ(v[i], 0);\n  }\n}\n\nTEST(SmallVector, ConstructionWithSizeAndValue) {\n  SmallVector<int> v(5, 42);\n  EXPECT_EQ(v.size(), 5u);\n  for (size_t i = 0; i < v.size(); ++i) {\n    EXPECT_EQ(v[i], 42);\n  }\n}\n\nTEST(SmallVector, InitializerListConstruction) {\n  SmallVector<int> v = {1, 2, 3, 4, 5};\n  EXPECT_EQ(v.size(), 5u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[4], 5);\n}\n\nTEST(SmallVector, CopyConstruction) {\n  SmallVector<int> v1 = {1, 2, 3};\n  SmallVector<int> v2(v1);\n  EXPECT_EQ(v2.size(), 3u);\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v2[1], 2);\n  EXPECT_EQ(v2[2], 3);\n  // Verify independence\n  v1[0] = 100;\n  EXPECT_EQ(v2[0], 1);\n}\n\nTEST(SmallVector, MoveConstructionInline) {\n  SmallVector<int, 8> v1 = {1, 2, 3};\n  SmallVector<int, 8> v2(std::move(v1));\n  EXPECT_EQ(v2.size(), 3u);\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v2[1], 2);\n  EXPECT_EQ(v2[2], 3);\n  EXPECT_EQ(v1.size(), 0u);\n}\n\nTEST(SmallVector, MoveConstructionHeap) {\n  SmallVector<int, 2> v1 = {1, 2, 3, 4, 5}; // Forces heap allocation\n  const int* oldData = v1.data();\n  SmallVector<int, 2> v2(std::move(v1));\n  EXPECT_EQ(v2.size(), 5u);\n  EXPECT_EQ(v2.data(), oldData); // Should steal the pointer\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v2[4], 5);\n  EXPECT_EQ(v1.size(), 0u);\n}\n\n// --- Assignment Tests ---\n\nTEST(SmallVector, CopyAssignment) {\n  SmallVector<int> v1 = {1, 2, 3};\n  SmallVector<int> v2;\n  v2 = v1;\n  EXPECT_EQ(v2.size(), 3u);\n  EXPECT_EQ(v2[0], 1);\n  v1[0] = 100;\n  EXPECT_EQ(v2[0], 1);\n}\n\nTEST(SmallVector, MoveAssignment) {\n  SmallVector<int, 2> v1 = {1, 2, 3, 4, 5};\n  SmallVector<int, 2> v2;\n  v2 = std::move(v1);\n  EXPECT_EQ(v2.size(), 5u);\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v1.size(), 0u);\n}\n\nTEST(SmallVector, MoveAssignmentHeapToHeap) {\n  // Target has heap storage that needs to be freed\n  SmallVector<int, 2> v1 = {1, 2, 3, 4, 5};\n  SmallVector<int, 2> v2 = {10, 20, 30, 40}; // Also on heap\n  v2 = std::move(v1);\n  EXPECT_EQ(v2.size(), 5u);\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v1.size(), 0u);\n}\n\nTEST(SmallVector, MoveAssignmentInlineToHeap) {\n  // Target has heap storage, source is inline\n  SmallVector<int, 4> v1 = {1, 2}; // Inline\n  SmallVector<int, 4> v2 = {10, 20, 30, 40, 50, 60}; // Heap\n  v2 = std::move(v1);\n  EXPECT_EQ(v2.size(), 2u);\n  EXPECT_EQ(v2[0], 1);\n  EXPECT_EQ(v2[1], 2);\n  EXPECT_EQ(v1.size(), 0u);\n}\n\nTEST(SmallVector, SelfAssignment) {\n  SmallVector<int> v = {1, 2, 3};\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wself-assign-overloaded\"\n#endif\n  v = v;\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n  EXPECT_EQ(v.size(), 3u);\n  EXPECT_EQ(v[0], 1);\n}\n\n// --- Element Access Tests ---\n\nTEST(SmallVector, OperatorBracket) {\n  SmallVector<int> v = {10, 20, 30};\n  EXPECT_EQ(v[0], 10);\n  EXPECT_EQ(v[1], 20);\n  EXPECT_EQ(v[2], 30);\n  v[1] = 25;\n  EXPECT_EQ(v[1], 25);\n}\n\nTEST(SmallVector, FrontAndBack) {\n  SmallVector<int> v = {1, 2, 3};\n  EXPECT_EQ(v.front(), 1);\n  EXPECT_EQ(v.back(), 3);\n  v.front() = 10;\n  v.back() = 30;\n  EXPECT_EQ(v.front(), 10);\n  EXPECT_EQ(v.back(), 30);\n}\n\nTEST(SmallVector, Data) {\n  SmallVector<int> v = {1, 2, 3};\n  int* ptr = v.data();\n  EXPECT_EQ(ptr[0], 1);\n  EXPECT_EQ(ptr[1], 2);\n  EXPECT_EQ(ptr[2], 3);\n}\n\n// --- Capacity Tests ---\n\nTEST(SmallVector, Empty) {\n  SmallVector<int> v;\n  EXPECT_TRUE(v.empty());\n  v.push_back(1);\n  EXPECT_FALSE(v.empty());\n}\n\nTEST(SmallVector, Size) {\n  SmallVector<int> v;\n  EXPECT_EQ(v.size(), 0u);\n  v.push_back(1);\n  EXPECT_EQ(v.size(), 1u);\n  v.push_back(2);\n  EXPECT_EQ(v.size(), 2u);\n}\n\n// --- Modifier Tests ---\n\nTEST(SmallVector, PushBack) {\n  SmallVector<int> v;\n  v.push_back(1);\n  v.push_back(2);\n  v.push_back(3);\n  EXPECT_EQ(v.size(), 3u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n  EXPECT_EQ(v[2], 3);\n}\n\nTEST(SmallVector, PushBackGrowth) {\n  SmallVector<int, 2> v;\n  v.push_back(1);\n  v.push_back(2);\n  EXPECT_EQ(v.capacity(), 2u);\n  v.push_back(3); // Should trigger growth\n  EXPECT_GT(v.capacity(), 2u);\n  EXPECT_EQ(v.size(), 3u);\n  EXPECT_EQ(v[2], 3);\n}\n\nTEST(SmallVector, EmplaceBack) {\n  SmallVector<std::pair<int, int>> v;\n  v.emplace_back(1, 2);\n  v.emplace_back(3, 4);\n  EXPECT_EQ(v.size(), 2u);\n  EXPECT_EQ(v[0].first, 1);\n  EXPECT_EQ(v[0].second, 2);\n  EXPECT_EQ(v[1].first, 3);\n  EXPECT_EQ(v[1].second, 4);\n}\n\nTEST(SmallVector, PopBack) {\n  SmallVector<int> v = {1, 2, 3};\n  v.pop_back();\n  EXPECT_EQ(v.size(), 2u);\n  EXPECT_EQ(v.back(), 2);\n  v.pop_back();\n  EXPECT_EQ(v.size(), 1u);\n  EXPECT_EQ(v.back(), 1);\n}\n\nTEST(SmallVector, Clear) {\n  SmallVector<int> v = {1, 2, 3, 4, 5};\n  v.clear();\n  EXPECT_TRUE(v.empty());\n  EXPECT_EQ(v.size(), 0u);\n}\n\nTEST(SmallVector, ResizeGrow) {\n  SmallVector<int> v = {1, 2};\n  v.resize(5);\n  EXPECT_EQ(v.size(), 5u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n  EXPECT_EQ(v[2], 0);\n  EXPECT_EQ(v[3], 0);\n  EXPECT_EQ(v[4], 0);\n}\n\nTEST(SmallVector, ResizeShrink) {\n  SmallVector<int> v = {1, 2, 3, 4, 5};\n  v.resize(2);\n  EXPECT_EQ(v.size(), 2u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n}\n\nTEST(SmallVector, ResizeWithValue) {\n  SmallVector<int> v = {1, 2};\n  v.resize(5, 42);\n  EXPECT_EQ(v.size(), 5u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n  EXPECT_EQ(v[2], 42);\n  EXPECT_EQ(v[3], 42);\n  EXPECT_EQ(v[4], 42);\n}\n\nTEST(SmallVector, EraseMiddle) {\n  SmallVector<int> v = {1, 2, 3, 4, 5};\n  auto it = v.erase(v.begin() + 2);\n  EXPECT_EQ(v.size(), 4u);\n  EXPECT_EQ(*it, 4);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n  EXPECT_EQ(v[2], 4);\n  EXPECT_EQ(v[3], 5);\n}\n\nTEST(SmallVector, EraseFirst) {\n  SmallVector<int> v = {1, 2, 3};\n  v.erase(v.begin());\n  EXPECT_EQ(v.size(), 2u);\n  EXPECT_EQ(v[0], 2);\n  EXPECT_EQ(v[1], 3);\n}\n\nTEST(SmallVector, EraseLast) {\n  SmallVector<int> v = {1, 2, 3};\n  v.erase(v.end() - 1);\n  EXPECT_EQ(v.size(), 2u);\n  EXPECT_EQ(v[0], 1);\n  EXPECT_EQ(v[1], 2);\n}\n\n// --- Iterator Tests ---\n\nTEST(SmallVector, RangeBasedFor) {\n  SmallVector<int> v = {1, 2, 3, 4, 5};\n  int sum = 0;\n  for (int x : v) {\n    sum += x;\n  }\n  EXPECT_EQ(sum, 15);\n}\n\nTEST(SmallVector, ConstIteration) {\n  const SmallVector<int> v = {1, 2, 3};\n  int sum = 0;\n  for (const int& x : v) {\n    sum += x;\n  }\n  EXPECT_EQ(sum, 6);\n}\n\nTEST(SmallVector, BeginEnd) {\n  SmallVector<int> v = {1, 2, 3};\n  EXPECT_EQ(*v.begin(), 1);\n  EXPECT_EQ(*(v.end() - 1), 3);\n  EXPECT_EQ(v.end() - v.begin(), 3);\n}\n\nTEST(SmallVector, CBeginCEnd) {\n  SmallVector<int> v = {1, 2, 3};\n  EXPECT_EQ(*v.cbegin(), 1);\n  EXPECT_EQ(*(v.cend() - 1), 3);\n  EXPECT_EQ(v.cend() - v.cbegin(), 3);\n}\n\nTEST(SmallVector, ConstAccessors) {\n  const SmallVector<int> v = {10, 20, 30};\n  EXPECT_EQ(v[0], 10);\n  EXPECT_EQ(v[2], 30);\n  EXPECT_EQ(v.front(), 10);\n  EXPECT_EQ(v.back(), 30);\n  EXPECT_EQ(v.data()[1], 20);\n  EXPECT_EQ(*v.begin(), 10);\n  EXPECT_EQ(*(v.end() - 1), 30);\n}\n\n// --- Object Lifetime Tests ---\n\nTEST(SmallVector, DestructorsCalled) {\n  Tracked::reset();\n  {\n    SmallVector<Tracked, 4> v;\n    v.emplace_back(1);\n    v.emplace_back(2);\n    v.emplace_back(3);\n    EXPECT_EQ(Tracked::constructed, 3);\n    EXPECT_EQ(Tracked::destructed, 0);\n  }\n  EXPECT_EQ(Tracked::constructed, Tracked::destructed);\n}\n\nTEST(SmallVector, DestructorsCalledOnClear) {\n  Tracked::reset();\n  SmallVector<Tracked, 4> v;\n  v.emplace_back(1);\n  v.emplace_back(2);\n  int beforeClear = Tracked::destructed;\n  v.clear();\n  EXPECT_EQ(Tracked::destructed - beforeClear, 2);\n}\n\nTEST(SmallVector, DestructorsCalledOnGrowth) {\n  Tracked::reset();\n  SmallVector<Tracked, 2> v;\n  v.emplace_back(1);\n  v.emplace_back(2);\n  int beforeGrowth = Tracked::destructed;\n  v.emplace_back(3); // Triggers growth, should move and destroy old\n  EXPECT_EQ(Tracked::destructed - beforeGrowth, 2); // Old elements destroyed\n  EXPECT_EQ(Tracked::moveConstructed, 2); // Old elements moved to new storage\n}\n\nTEST(SmallVector, MoveSemantics) {\n  Tracked::reset();\n  SmallVector<Tracked, 2> v1;\n  v1.emplace_back(1);\n  v1.emplace_back(2);\n\n  int constructedBefore = Tracked::constructed;\n  SmallVector<Tracked, 2> v2(std::move(v1));\n  // Inline move should move-construct elements\n  EXPECT_EQ(Tracked::constructed - constructedBefore, 2);\n  EXPECT_EQ(v2.size(), 2u);\n  EXPECT_EQ(v2[0].value, 1);\n  EXPECT_EQ(v2[1].value, 2);\n}\n\n// --- String Tests (non-trivial type) ---\n\nTEST(SmallVector, StringOperations) {\n  SmallVector<std::string, 4> v;\n  v.push_back(\"hello\");\n  v.push_back(\"world\");\n  v.emplace_back(\"!\");\n  EXPECT_EQ(v.size(), 3u);\n  EXPECT_EQ(v[0], \"hello\");\n  EXPECT_EQ(v[1], \"world\");\n  EXPECT_EQ(v[2], \"!\");\n}\n\nTEST(SmallVector, StringGrowth) {\n  SmallVector<std::string, 2> v;\n  v.push_back(\"one\");\n  v.push_back(\"two\");\n  v.push_back(\"three\");\n  v.push_back(\"four\");\n  EXPECT_EQ(v.size(), 4u);\n  EXPECT_EQ(v[0], \"one\");\n  EXPECT_EQ(v[3], \"four\");\n}\n\n// --- Edge Cases ---\n\nTEST(SmallVector, LargeInlineCapacity) {\n  SmallVector<int, 100> v;\n  for (int i = 0; i < 100; ++i) {\n    v.push_back(i);\n  }\n  EXPECT_EQ(v.size(), 100u);\n  EXPECT_EQ(v.capacity(), 100u); // Should still be inline\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(v[static_cast<size_t>(i)], i);\n  }\n}\n\nTEST(SmallVector, DifferentInlineCapacities) {\n  SmallVector<int, 2> v2 = {1, 2};\n  SmallVector<int, 8> v8 = {1, 2, 3, 4, 5, 6, 7, 8};\n  EXPECT_EQ(v2.size(), 2u);\n  EXPECT_EQ(v8.size(), 8u);\n}\n\n// --- Heap regrowth tests (exceed 2*N to trigger heap→heap growth) ---\n\nTEST(SmallVector, HeapRegrowth) {\n  SmallVector<int, 4> v;\n  // Push 20 elements: inline(4) → heap(8) → heap(16) → heap(32)\n  for (int i = 0; i < 20; ++i) {\n    v.push_back(i);\n  }\n  EXPECT_EQ(v.size(), 20u);\n  EXPECT_GE(v.capacity(), 20u);\n  for (int i = 0; i < 20; ++i) {\n    EXPECT_EQ(v[static_cast<size_t>(i)], i);\n  }\n}\n\nTEST(SmallVector, HeapRegrowthWithReserve) {\n  SmallVector<int, 4> v;\n  v.reserve(100);\n  EXPECT_GE(v.capacity(), 100u);\n  for (int i = 0; i < 100; ++i) {\n    v.push_back(i);\n  }\n  EXPECT_EQ(v.size(), 100u);\n  for (int i = 0; i < 100; ++i) {\n    EXPECT_EQ(v[static_cast<size_t>(i)], i);\n  }\n}\n\nTEST(SmallVector, HeapRegrowthTracked) {\n  Tracked::reset();\n  {\n    SmallVector<Tracked, 2> v;\n    for (int i = 0; i < 10; ++i) {\n      v.emplace_back(i);\n    }\n    EXPECT_EQ(v.size(), 10u);\n    for (int i = 0; i < 10; ++i) {\n      EXPECT_EQ(v[static_cast<size_t>(i)].value, i);\n    }\n  }\n  EXPECT_EQ(Tracked::constructed, Tracked::destructed);\n}\n\nTEST(SmallVector, EraseOnHeap) {\n  SmallVector<int, 2> v;\n  for (int i = 0; i < 8; ++i) {\n    v.push_back(i);\n  }\n  // Erase from the middle while on heap\n  v.erase(v.begin() + 3);\n  EXPECT_EQ(v.size(), 7u);\n  EXPECT_EQ(v[0], 0);\n  EXPECT_EQ(v[1], 1);\n  EXPECT_EQ(v[2], 2);\n  EXPECT_EQ(v[3], 4); // was 3, now shifted\n  EXPECT_EQ(v[6], 7);\n}\n\nTEST(SmallVector, PopBackOnHeap) {\n  SmallVector<int, 2> v;\n  for (int i = 0; i < 8; ++i) {\n    v.push_back(i);\n  }\n  v.pop_back();\n  v.pop_back();\n  EXPECT_EQ(v.size(), 6u);\n  EXPECT_EQ(v.back(), 5);\n}\n"
  },
  {
    "path": "tests/spsc_ring_buffer_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/spsc_ring_buffer.h>\n\n#include <array>\n#include <atomic>\n#include <memory>\n#include <string>\n#include <thread>\n#include <vector>\n\n#include <gtest/gtest.h>\n\nusing dispenso::SPSCRingBuffer;\n\n// =============================================================================\n// Basic Functionality Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, DefaultConstructionIsEmpty) {\n  SPSCRingBuffer<int> buffer;\n  EXPECT_TRUE(buffer.empty());\n  EXPECT_FALSE(buffer.full());\n  EXPECT_EQ(buffer.size(), 0u);\n}\n\nTEST(SPSCRingBuffer, CapacityIsCorrect) {\n  // With RoundUpToPowerOfTwo=true (default), capacity is rounded up to next power of two minus 1\n  // Capacity=8: buffer size = nextPowerOfTwo(9) = 16, actual capacity = 15\n  SPSCRingBuffer<int, 8> buffer8;\n  EXPECT_EQ(buffer8.capacity(), 15u);\n\n  // Capacity=1: buffer size = nextPowerOfTwo(2) = 2, actual capacity = 1\n  SPSCRingBuffer<int, 1> buffer1;\n  EXPECT_EQ(buffer1.capacity(), 1u);\n\n  // Capacity=100: buffer size = nextPowerOfTwo(101) = 128, actual capacity = 127\n  SPSCRingBuffer<int, 100> buffer100;\n  EXPECT_EQ(buffer100.capacity(), 127u);\n\n  // Default capacity (16): buffer size = nextPowerOfTwo(17) = 32, actual capacity = 31\n  SPSCRingBuffer<int> bufferDefault;\n  EXPECT_EQ(bufferDefault.capacity(), 31u);\n\n  // With RoundUpToPowerOfTwo=false, capacity matches the template parameter exactly\n  SPSCRingBuffer<int, 8, false> exactBuffer8;\n  EXPECT_EQ(exactBuffer8.capacity(), 8u);\n\n  SPSCRingBuffer<int, 100, false> exactBuffer100;\n  EXPECT_EQ(exactBuffer100.capacity(), 100u);\n}\n\nTEST(SPSCRingBuffer, PushAndPopSingleElement) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  EXPECT_TRUE(buffer.try_push(42));\n  EXPECT_FALSE(buffer.empty());\n  EXPECT_EQ(buffer.size(), 1u);\n\n  int value = 0;\n  EXPECT_TRUE(buffer.try_pop(value));\n  EXPECT_EQ(value, 42);\n  EXPECT_TRUE(buffer.empty());\n  EXPECT_EQ(buffer.size(), 0u);\n}\n\nTEST(SPSCRingBuffer, PushMoveSemantics) {\n  SPSCRingBuffer<std::string, 4> buffer;\n\n  std::string original = \"hello world\";\n  EXPECT_TRUE(buffer.try_push(std::move(original)));\n  // After move, original should be empty (or at least valid but unspecified)\n  EXPECT_TRUE(original.empty());\n\n  std::string result;\n  EXPECT_TRUE(buffer.try_pop(result));\n  EXPECT_EQ(result, \"hello world\");\n}\n\nTEST(SPSCRingBuffer, PushCopySemantics) {\n  SPSCRingBuffer<std::string, 4> buffer;\n\n  std::string original = \"hello world\";\n  EXPECT_TRUE(buffer.try_push(original));\n  // After copy, original should be unchanged\n  EXPECT_EQ(original, \"hello world\");\n\n  std::string result;\n  EXPECT_TRUE(buffer.try_pop(result));\n  EXPECT_EQ(result, \"hello world\");\n}\n\nTEST(SPSCRingBuffer, TryEmplace) {\n  SPSCRingBuffer<std::pair<int, std::string>, 4> buffer;\n\n  EXPECT_TRUE(buffer.try_emplace(42, \"hello\"));\n  EXPECT_EQ(buffer.size(), 1u);\n\n  std::pair<int, std::string> result;\n  EXPECT_TRUE(buffer.try_pop(result));\n  EXPECT_EQ(result.first, 42);\n  EXPECT_EQ(result.second, \"hello\");\n}\n\nTEST(SPSCRingBuffer, PopFromEmpty) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  int value = 999;\n  EXPECT_FALSE(buffer.try_pop(value));\n  // Value should be unchanged\n  EXPECT_EQ(value, 999);\n}\n\nTEST(SPSCRingBuffer, TryPopReturnsOpResult) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  // Pop from empty returns empty OpResult\n  auto emptyResult = buffer.try_pop();\n  EXPECT_FALSE(emptyResult);\n  EXPECT_FALSE(emptyResult.has_value());\n\n  // Push and pop returns value\n  EXPECT_TRUE(buffer.try_push(42));\n  auto result = buffer.try_pop();\n  EXPECT_TRUE(result);\n  EXPECT_TRUE(result.has_value());\n  EXPECT_EQ(result.value(), 42);\n  EXPECT_TRUE(buffer.empty());\n}\n\nTEST(SPSCRingBuffer, TryPopOpResultWithMoveOnlyType) {\n  SPSCRingBuffer<std::unique_ptr<int>, 4> buffer;\n\n  // Push a unique_ptr\n  EXPECT_TRUE(buffer.try_push(std::make_unique<int>(123)));\n\n  // Pop using OpResult\n  auto result = buffer.try_pop();\n  EXPECT_TRUE(result);\n  EXPECT_NE(result.value(), nullptr);\n  EXPECT_EQ(*result.value(), 123);\n}\n\nTEST(SPSCRingBuffer, TryPopOpResultWithString) {\n  SPSCRingBuffer<std::string, 4> buffer;\n\n  EXPECT_TRUE(buffer.try_push(\"hello world\"));\n  auto result = buffer.try_pop();\n  EXPECT_TRUE(result);\n  EXPECT_EQ(result.value(), \"hello world\");\n}\n\nTEST(SPSCRingBuffer, FIFOOrder) {\n  SPSCRingBuffer<int, 8> buffer;\n\n  for (int i = 0; i < 5; ++i) {\n    EXPECT_TRUE(buffer.try_push(i));\n  }\n\n  for (int i = 0; i < 5; ++i) {\n    int value = -1;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, i);\n  }\n}\n\n// =============================================================================\n// Capacity and Full/Empty Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, FillToCapacity) {\n  SPSCRingBuffer<int, 4> buffer;\n  const size_t cap = buffer.capacity();\n\n  // Fill buffer to capacity\n  for (size_t i = 0; i < cap; ++i) {\n    EXPECT_FALSE(buffer.full());\n    EXPECT_TRUE(buffer.try_push(static_cast<int>(i)));\n  }\n\n  EXPECT_TRUE(buffer.full());\n  EXPECT_EQ(buffer.size(), cap);\n\n  // Additional push should fail\n  EXPECT_FALSE(buffer.try_push(100));\n  EXPECT_EQ(buffer.size(), cap);\n}\n\nTEST(SPSCRingBuffer, FullThenPop) {\n  SPSCRingBuffer<int, 4> buffer;\n  const size_t cap = buffer.capacity();\n\n  // Fill buffer\n  for (size_t i = 0; i < cap; ++i) {\n    EXPECT_TRUE(buffer.try_push(static_cast<int>(i)));\n  }\n  EXPECT_TRUE(buffer.full());\n\n  // Pop one element\n  int value;\n  EXPECT_TRUE(buffer.try_pop(value));\n  EXPECT_EQ(value, 0);\n  EXPECT_FALSE(buffer.full());\n\n  // Now push should succeed again\n  EXPECT_TRUE(buffer.try_push(100));\n  EXPECT_TRUE(buffer.full());\n}\n\nTEST(SPSCRingBuffer, CapacityOne) {\n  SPSCRingBuffer<int, 1> buffer;\n\n  EXPECT_TRUE(buffer.empty());\n  EXPECT_FALSE(buffer.full());\n\n  EXPECT_TRUE(buffer.try_push(42));\n  EXPECT_FALSE(buffer.empty());\n  EXPECT_TRUE(buffer.full());\n\n  EXPECT_FALSE(buffer.try_push(43));\n\n  int value;\n  EXPECT_TRUE(buffer.try_pop(value));\n  EXPECT_EQ(value, 42);\n  EXPECT_TRUE(buffer.empty());\n}\n\nTEST(SPSCRingBuffer, SizeTracking) {\n  SPSCRingBuffer<int, 8> buffer;\n\n  for (size_t i = 0; i < 8; ++i) {\n    EXPECT_EQ(buffer.size(), i);\n    EXPECT_TRUE(buffer.try_push(static_cast<int>(i)));\n  }\n  EXPECT_EQ(buffer.size(), 8u);\n\n  for (size_t i = 8; i > 0; --i) {\n    EXPECT_EQ(buffer.size(), i);\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n  }\n  EXPECT_EQ(buffer.size(), 0u);\n}\n\n// =============================================================================\n// Wrap-around Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, WrapAround) {\n  // Use exact capacity mode for predictable wrap-around behavior in this test\n  SPSCRingBuffer<int, 4, false> buffer;\n\n  // Push 3 elements\n  for (int i = 0; i < 3; ++i) {\n    EXPECT_TRUE(buffer.try_push(i));\n  }\n\n  // Pop 2 elements (advances head)\n  for (int i = 0; i < 2; ++i) {\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, i);\n  }\n\n  // Push 3 more elements (will wrap around)\n  for (int i = 10; i < 13; ++i) {\n    EXPECT_TRUE(buffer.try_push(i));\n  }\n\n  // Should have 4 elements now: 2, 10, 11, 12\n  EXPECT_EQ(buffer.size(), 4u);\n  EXPECT_TRUE(buffer.full());\n\n  // Pop all and verify order\n  int expected[] = {2, 10, 11, 12};\n  for (int exp : expected) {\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, exp);\n  }\n}\n\nTEST(SPSCRingBuffer, MultipleWrapArounds) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  // Perform many push/pop cycles to test wrap-around thoroughly\n  for (int cycle = 0; cycle < 100; ++cycle) {\n    for (int i = 0; i < 3; ++i) {\n      EXPECT_TRUE(buffer.try_push(cycle * 10 + i));\n    }\n    for (int i = 0; i < 3; ++i) {\n      int value;\n      EXPECT_TRUE(buffer.try_pop(value));\n      EXPECT_EQ(value, cycle * 10 + i);\n    }\n    EXPECT_TRUE(buffer.empty());\n  }\n}\n\nTEST(SPSCRingBuffer, SizeWithWrapAround) {\n  // Use exact capacity mode for predictable size behavior\n  SPSCRingBuffer<int, 4, false> buffer;\n\n  // Fill halfway\n  buffer.try_push(1);\n  buffer.try_push(2);\n\n  // Pop one\n  int v;\n  buffer.try_pop(v);\n\n  // Push to full (will wrap)\n  buffer.try_push(3);\n  buffer.try_push(4);\n  buffer.try_push(5);\n\n  EXPECT_EQ(buffer.size(), 4u);\n  EXPECT_TRUE(buffer.full());\n}\n\n// =============================================================================\n// Move-only Type Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, MoveOnlyType) {\n  SPSCRingBuffer<std::unique_ptr<int>, 4> buffer;\n\n  auto ptr = std::make_unique<int>(42);\n  EXPECT_TRUE(buffer.try_push(std::move(ptr)));\n  EXPECT_EQ(ptr, nullptr);\n\n  std::unique_ptr<int> result;\n  EXPECT_TRUE(buffer.try_pop(result));\n  EXPECT_NE(result, nullptr);\n  EXPECT_EQ(*result, 42);\n}\n\nTEST(SPSCRingBuffer, MoveOnlyTypeMultiple) {\n  SPSCRingBuffer<std::unique_ptr<int>, 4> buffer;\n\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_TRUE(buffer.try_push(std::make_unique<int>(i)));\n  }\n\n  for (int i = 0; i < 4; ++i) {\n    std::unique_ptr<int> result;\n    EXPECT_TRUE(buffer.try_pop(result));\n    EXPECT_EQ(*result, i);\n  }\n}\n\n// =============================================================================\n// Non-trivial Type Tests\n// =============================================================================\n\nnamespace {\nstruct NonTrivial {\n  static std::atomic<int> constructorCount;\n  static std::atomic<int> destructorCount;\n  static std::atomic<int> moveCount;\n\n  int value;\n\n  NonTrivial() : value(0) {\n    constructorCount.fetch_add(1, std::memory_order_relaxed);\n  }\n  explicit NonTrivial(int v) : value(v) {\n    constructorCount.fetch_add(1, std::memory_order_relaxed);\n  }\n  NonTrivial(const NonTrivial& other) : value(other.value) {\n    constructorCount.fetch_add(1, std::memory_order_relaxed);\n  }\n  NonTrivial(NonTrivial&& other) noexcept : value(other.value) {\n    other.value = -1;\n    moveCount.fetch_add(1, std::memory_order_relaxed);\n  }\n  NonTrivial& operator=(const NonTrivial& other) {\n    value = other.value;\n    return *this;\n  }\n  NonTrivial& operator=(NonTrivial&& other) noexcept {\n    value = other.value;\n    other.value = -1;\n    moveCount.fetch_add(1, std::memory_order_relaxed);\n    return *this;\n  }\n  ~NonTrivial() {\n    destructorCount.fetch_add(1, std::memory_order_relaxed);\n  }\n\n  static void resetCounters() {\n    constructorCount.store(0, std::memory_order_relaxed);\n    destructorCount.store(0, std::memory_order_relaxed);\n    moveCount.store(0, std::memory_order_relaxed);\n  }\n};\n\nstd::atomic<int> NonTrivial::constructorCount{0};\nstd::atomic<int> NonTrivial::destructorCount{0};\nstd::atomic<int> NonTrivial::moveCount{0};\n} // namespace\n\nTEST(SPSCRingBuffer, NonTrivialType) {\n  NonTrivial::resetCounters();\n\n  {\n    SPSCRingBuffer<NonTrivial, 4> buffer;\n\n    NonTrivial obj(42);\n    EXPECT_TRUE(buffer.try_push(std::move(obj)));\n\n    NonTrivial result;\n    EXPECT_TRUE(buffer.try_pop(result));\n    EXPECT_EQ(result.value, 42);\n  }\n\n  // All objects should be destroyed\n  // (buffer storage + temporary objects)\n}\n\nTEST(SPSCRingBuffer, NonTrivialDestructorOnBufferDestruction) {\n  NonTrivial::resetCounters();\n\n  {\n    SPSCRingBuffer<NonTrivial, 4> buffer;\n\n    buffer.try_push(NonTrivial(1));\n    buffer.try_push(NonTrivial(2));\n    buffer.try_push(NonTrivial(3));\n    // Buffer goes out of scope with 3 elements\n  }\n\n  // Destructor should have been called for all elements\n}\n\n// =============================================================================\n// Concurrent Producer-Consumer Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, ConcurrentProducerConsumer) {\n  SPSCRingBuffer<int, 16> buffer;\n  constexpr int kNumItems = 100000;\n\n  std::atomic<bool> producerDone{false};\n  std::vector<int> consumed;\n  consumed.reserve(kNumItems);\n\n  // Producer thread\n  std::thread producer([&]() {\n    for (int i = 0; i < kNumItems; ++i) {\n      while (!buffer.try_push(i)) {\n        // Spin until space available\n        std::this_thread::yield();\n      }\n    }\n    producerDone.store(true, std::memory_order_release);\n  });\n\n  // Consumer thread\n  std::thread consumer([&]() {\n    int value;\n    while (consumed.size() < static_cast<size_t>(kNumItems)) {\n      if (buffer.try_pop(value)) {\n        consumed.push_back(value);\n      } else if (producerDone.load(std::memory_order_acquire) && buffer.empty()) {\n        break;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  producer.join();\n  consumer.join();\n\n  // Verify all items received in order\n  ASSERT_EQ(consumed.size(), kNumItems);\n  for (int i = 0; i < kNumItems; ++i) {\n    EXPECT_EQ(consumed[i], i) << \"Mismatch at index \" << i;\n  }\n}\n\nTEST(SPSCRingBuffer, ConcurrentWithSmallBuffer) {\n  // Small buffer to increase contention\n  SPSCRingBuffer<int, 2> buffer;\n  constexpr int kNumItems = 10000;\n\n  std::atomic<bool> producerDone{false};\n  std::vector<int> consumed;\n  consumed.reserve(kNumItems);\n\n  std::thread producer([&]() {\n    for (int i = 0; i < kNumItems; ++i) {\n      while (!buffer.try_push(i)) {\n        std::this_thread::yield();\n      }\n    }\n    producerDone.store(true, std::memory_order_release);\n  });\n\n  std::thread consumer([&]() {\n    int value;\n    while (consumed.size() < static_cast<size_t>(kNumItems)) {\n      if (buffer.try_pop(value)) {\n        consumed.push_back(value);\n      } else if (producerDone.load(std::memory_order_acquire) && buffer.empty()) {\n        break;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  producer.join();\n  consumer.join();\n\n  ASSERT_EQ(consumed.size(), kNumItems);\n  for (int i = 0; i < kNumItems; ++i) {\n    EXPECT_EQ(consumed[i], i);\n  }\n}\n\nTEST(SPSCRingBuffer, ConcurrentWithMoveOnlyType) {\n  SPSCRingBuffer<std::unique_ptr<int>, 8> buffer;\n  constexpr int kNumItems = 10000;\n\n  std::atomic<bool> producerDone{false};\n  std::vector<int> consumed;\n  consumed.reserve(kNumItems);\n\n  std::thread producer([&]() {\n    for (int i = 0; i < kNumItems; ++i) {\n      auto ptr = std::make_unique<int>(i);\n      while (!buffer.try_push(std::move(ptr))) {\n        std::this_thread::yield();\n      }\n    }\n    producerDone.store(true, std::memory_order_release);\n  });\n\n  std::thread consumer([&]() {\n    std::unique_ptr<int> value;\n    while (consumed.size() < static_cast<size_t>(kNumItems)) {\n      if (buffer.try_pop(value)) {\n        consumed.push_back(*value);\n        value.reset();\n      } else if (producerDone.load(std::memory_order_acquire) && buffer.empty()) {\n        break;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  producer.join();\n  consumer.join();\n\n  ASSERT_EQ(consumed.size(), kNumItems);\n  for (int i = 0; i < kNumItems; ++i) {\n    EXPECT_EQ(consumed[i], i);\n  }\n}\n\n// =============================================================================\n// Edge Cases\n// =============================================================================\n\nTEST(SPSCRingBuffer, EmptyAfterDraining) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  buffer.try_push(1);\n  buffer.try_push(2);\n\n  int v;\n  buffer.try_pop(v);\n  buffer.try_pop(v);\n\n  EXPECT_TRUE(buffer.empty());\n  EXPECT_EQ(buffer.size(), 0u);\n  EXPECT_FALSE(buffer.try_pop(v));\n}\n\nTEST(SPSCRingBuffer, RepeatedFillAndDrain) {\n  SPSCRingBuffer<int, 4> buffer;\n  const size_t cap = buffer.capacity();\n\n  for (int cycle = 0; cycle < 10; ++cycle) {\n    // Fill completely\n    for (size_t i = 0; i < cap; ++i) {\n      EXPECT_TRUE(buffer.try_push(cycle * 10 + static_cast<int>(i)));\n    }\n    EXPECT_TRUE(buffer.full());\n    EXPECT_FALSE(buffer.try_push(999));\n\n    // Drain completely\n    for (size_t i = 0; i < cap; ++i) {\n      int value;\n      EXPECT_TRUE(buffer.try_pop(value));\n      EXPECT_EQ(value, cycle * 10 + static_cast<int>(i));\n    }\n    EXPECT_TRUE(buffer.empty());\n    int dummy;\n    EXPECT_FALSE(buffer.try_pop(dummy));\n  }\n}\n\nTEST(SPSCRingBuffer, AlternatingPushPop) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  for (int i = 0; i < 1000; ++i) {\n    EXPECT_TRUE(buffer.try_push(i));\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, i);\n    EXPECT_TRUE(buffer.empty());\n  }\n}\n\nTEST(SPSCRingBuffer, LargeElements) {\n  struct LargeStruct {\n    std::array<char, 1024> data;\n    int id;\n\n    LargeStruct() : id(0) {\n      data.fill('x');\n    }\n    explicit LargeStruct(int i) : id(i) {\n      data.fill(static_cast<char>('0' + (i % 10)));\n    }\n  };\n\n  SPSCRingBuffer<LargeStruct, 4> buffer;\n\n  for (int i = 0; i < 4; ++i) {\n    EXPECT_TRUE(buffer.try_push(LargeStruct(i)));\n  }\n\n  for (int i = 0; i < 4; ++i) {\n    LargeStruct value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value.id, i);\n    EXPECT_EQ(value.data[0], static_cast<char>('0' + i));\n  }\n}\n\n// =============================================================================\n// String Type Tests (common use case)\n// =============================================================================\n\nTEST(SPSCRingBuffer, StringElements) {\n  SPSCRingBuffer<std::string, 8> buffer;\n\n  std::vector<std::string> testStrings = {\n      \"hello\", \"world\", \"this is a longer string\", \"\", \"short\", \"another test string\"};\n\n  for (const auto& s : testStrings) {\n    EXPECT_TRUE(buffer.try_push(s));\n  }\n\n  for (const auto& expected : testStrings) {\n    std::string result;\n    EXPECT_TRUE(buffer.try_pop(result));\n    EXPECT_EQ(result, expected);\n  }\n}\n\n// =============================================================================\n// try_pop_into Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, TryPopIntoBasic) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  buffer.try_push(42);\n  buffer.try_push(100);\n\n  alignas(int) char storage[sizeof(int)];\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<int*>(storage)));\n\n  int* value = reinterpret_cast<int*>(storage);\n  EXPECT_EQ(*value, 42);\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<int*>(storage)));\n  EXPECT_EQ(*value, 100);\n\n  EXPECT_FALSE(buffer.try_pop_into(reinterpret_cast<int*>(storage)));\n}\n\nTEST(SPSCRingBuffer, TryPopIntoMoveOnly) {\n  SPSCRingBuffer<std::unique_ptr<int>, 4> buffer;\n\n  buffer.try_push(std::make_unique<int>(42));\n  buffer.try_push(std::make_unique<int>(100));\n\n  alignas(std::unique_ptr<int>) char storage[sizeof(std::unique_ptr<int>)];\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<std::unique_ptr<int>*>(storage)));\n  auto* ptr = reinterpret_cast<std::unique_ptr<int>*>(storage);\n  EXPECT_EQ(**ptr, 42);\n  ptr->~unique_ptr();\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<std::unique_ptr<int>*>(storage)));\n  ptr = reinterpret_cast<std::unique_ptr<int>*>(storage);\n  EXPECT_EQ(**ptr, 100);\n  ptr->~unique_ptr();\n\n  EXPECT_FALSE(buffer.try_pop_into(reinterpret_cast<std::unique_ptr<int>*>(storage)));\n}\n\nTEST(SPSCRingBuffer, TryPopIntoNonTrivial) {\n  NonTrivial::resetCounters();\n\n  SPSCRingBuffer<NonTrivial, 4> buffer;\n\n  buffer.try_push(NonTrivial(42));\n  buffer.try_push(NonTrivial(100));\n\n  int initialDestructorCount = NonTrivial::destructorCount.load();\n\n  alignas(NonTrivial) char storage[sizeof(NonTrivial)];\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<NonTrivial*>(storage)));\n  auto* obj = reinterpret_cast<NonTrivial*>(storage);\n  EXPECT_EQ(obj->value, 42);\n\n  // Destructor should have been called for the element in the buffer\n  EXPECT_GT(NonTrivial::destructorCount.load(), initialDestructorCount);\n\n  obj->~NonTrivial();\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<NonTrivial*>(storage)));\n  obj = reinterpret_cast<NonTrivial*>(storage);\n  EXPECT_EQ(obj->value, 100);\n  obj->~NonTrivial();\n}\n\n// =============================================================================\n// Non-Default-Constructible Type Tests\n// =============================================================================\n\nnamespace {\nstruct NonDefaultConstructible {\n  int value;\n\n  // No default constructor\n  explicit NonDefaultConstructible(int v) : value(v) {}\n  NonDefaultConstructible(const NonDefaultConstructible&) = default;\n  NonDefaultConstructible(NonDefaultConstructible&&) = default;\n  NonDefaultConstructible& operator=(const NonDefaultConstructible&) = default;\n  NonDefaultConstructible& operator=(NonDefaultConstructible&&) = default;\n};\n} // namespace\n\nTEST(SPSCRingBuffer, NonDefaultConstructibleType) {\n  SPSCRingBuffer<NonDefaultConstructible, 4> buffer;\n\n  EXPECT_TRUE(buffer.try_emplace(42));\n  EXPECT_TRUE(buffer.try_emplace(100));\n  EXPECT_EQ(buffer.size(), 2u);\n\n  // Use try_pop_into since we can't default-construct\n  alignas(NonDefaultConstructible) char storage[sizeof(NonDefaultConstructible)];\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<NonDefaultConstructible*>(storage)));\n  auto* obj = reinterpret_cast<NonDefaultConstructible*>(storage);\n  EXPECT_EQ(obj->value, 42);\n  obj->~NonDefaultConstructible();\n\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<NonDefaultConstructible*>(storage)));\n  obj = reinterpret_cast<NonDefaultConstructible*>(storage);\n  EXPECT_EQ(obj->value, 100);\n  obj->~NonDefaultConstructible();\n}\n\nTEST(SPSCRingBuffer, NonDefaultConstructibleWithMove) {\n  SPSCRingBuffer<NonDefaultConstructible, 4> buffer;\n\n  NonDefaultConstructible obj(42);\n  EXPECT_TRUE(buffer.try_push(std::move(obj)));\n\n  alignas(NonDefaultConstructible) char storage[sizeof(NonDefaultConstructible)];\n  EXPECT_TRUE(buffer.try_pop_into(reinterpret_cast<NonDefaultConstructible*>(storage)));\n  auto* result = reinterpret_cast<NonDefaultConstructible*>(storage);\n  EXPECT_EQ(result->value, 42);\n  result->~NonDefaultConstructible();\n}\n\n// =============================================================================\n// Large Capacity Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, LargeCapacity) {\n  SPSCRingBuffer<int, 1024> buffer;\n  const size_t cap = buffer.capacity();\n\n  // With rounding, 1024+1=1025 rounds up to 2048, so capacity is 2047\n  EXPECT_EQ(cap, 2047u);\n\n  // Fill to capacity\n  for (size_t i = 0; i < cap; ++i) {\n    EXPECT_TRUE(buffer.try_push(static_cast<int>(i)));\n  }\n  EXPECT_TRUE(buffer.full());\n  EXPECT_FALSE(buffer.try_push(9999));\n\n  // Drain and verify\n  for (size_t i = 0; i < cap; ++i) {\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, static_cast<int>(i));\n  }\n  EXPECT_TRUE(buffer.empty());\n}\n\nTEST(SPSCRingBuffer, LargeCapacityConcurrent) {\n  SPSCRingBuffer<int, 1024> buffer;\n  constexpr int kNumItems = 100000;\n\n  std::atomic<bool> producerDone{false};\n  std::vector<int> consumed;\n  consumed.reserve(kNumItems);\n\n  std::thread producer([&]() {\n    for (int i = 0; i < kNumItems; ++i) {\n      while (!buffer.try_push(i)) {\n        std::this_thread::yield();\n      }\n    }\n    producerDone.store(true, std::memory_order_release);\n  });\n\n  std::thread consumer([&]() {\n    int value;\n    while (consumed.size() < static_cast<size_t>(kNumItems)) {\n      if (buffer.try_pop(value)) {\n        consumed.push_back(value);\n      } else if (producerDone.load(std::memory_order_acquire) && buffer.empty()) {\n        break;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  producer.join();\n  consumer.join();\n\n  ASSERT_EQ(consumed.size(), kNumItems);\n  for (int i = 0; i < kNumItems; ++i) {\n    EXPECT_EQ(consumed[i], i);\n  }\n}\n\n// =============================================================================\n// Batch Operation Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, TryPushBatchBasic) {\n  SPSCRingBuffer<int, 8> buffer;\n\n  std::vector<int> items = {1, 2, 3, 4, 5};\n  size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n\n  EXPECT_EQ(pushed, 5u);\n  EXPECT_EQ(buffer.size(), 5u);\n\n  // Verify order\n  for (int i = 1; i <= 5; ++i) {\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, i);\n  }\n}\n\nTEST(SPSCRingBuffer, TryPushBatchPartial) {\n  // Use exact capacity mode for predictable partial push behavior\n  SPSCRingBuffer<int, 4, false> buffer;\n\n  // Try to push 6 items into capacity-4 buffer\n  std::vector<int> items = {1, 2, 3, 4, 5, 6};\n  size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n\n  EXPECT_EQ(pushed, 4u);\n  EXPECT_TRUE(buffer.full());\n\n  // Verify only first 4 items were pushed\n  for (int i = 1; i <= 4; ++i) {\n    int value;\n    EXPECT_TRUE(buffer.try_pop(value));\n    EXPECT_EQ(value, i);\n  }\n}\n\nTEST(SPSCRingBuffer, TryPushBatchEmpty) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  std::vector<int> items;\n  size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n\n  EXPECT_EQ(pushed, 0u);\n  EXPECT_TRUE(buffer.empty());\n}\n\nTEST(SPSCRingBuffer, TryPushBatchWhenFull) {\n  // Use exact capacity mode for predictable full behavior\n  SPSCRingBuffer<int, 4, false> buffer;\n\n  // Fill the buffer\n  for (int i = 0; i < 4; ++i) {\n    buffer.try_push(i);\n  }\n  EXPECT_TRUE(buffer.full());\n\n  std::vector<int> items = {10, 11, 12};\n  size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n\n  EXPECT_EQ(pushed, 0u);\n}\n\nTEST(SPSCRingBuffer, TryPopBatchBasic) {\n  SPSCRingBuffer<int, 8> buffer;\n\n  for (int i = 1; i <= 5; ++i) {\n    buffer.try_push(i);\n  }\n\n  std::vector<int> dest(5);\n  size_t popped = buffer.try_pop_batch(dest.begin(), 5);\n\n  EXPECT_EQ(popped, 5u);\n  EXPECT_TRUE(buffer.empty());\n\n  for (int i = 0; i < 5; ++i) {\n    EXPECT_EQ(dest[i], i + 1);\n  }\n}\n\nTEST(SPSCRingBuffer, TryPopBatchPartial) {\n  SPSCRingBuffer<int, 8> buffer;\n\n  for (int i = 1; i <= 3; ++i) {\n    buffer.try_push(i);\n  }\n\n  std::vector<int> dest(5, -1);\n  size_t popped = buffer.try_pop_batch(dest.begin(), 5);\n\n  EXPECT_EQ(popped, 3u);\n  EXPECT_TRUE(buffer.empty());\n\n  // First 3 should be set\n  EXPECT_EQ(dest[0], 1);\n  EXPECT_EQ(dest[1], 2);\n  EXPECT_EQ(dest[2], 3);\n  // Rest should be unchanged\n  EXPECT_EQ(dest[3], -1);\n  EXPECT_EQ(dest[4], -1);\n}\n\nTEST(SPSCRingBuffer, TryPopBatchEmpty) {\n  SPSCRingBuffer<int, 4> buffer;\n\n  std::vector<int> dest(4, -1);\n  size_t popped = buffer.try_pop_batch(dest.begin(), 4);\n\n  EXPECT_EQ(popped, 0u);\n  // Dest should be unchanged\n  for (int v : dest) {\n    EXPECT_EQ(v, -1);\n  }\n}\n\nTEST(SPSCRingBuffer, BatchWithWrapAround) {\n  // Use exact capacity mode for predictable wrap-around behavior\n  SPSCRingBuffer<int, 4, false> buffer;\n\n  // Push 3 items\n  for (int i = 0; i < 3; ++i) {\n    buffer.try_push(i);\n  }\n\n  // Pop 2 items (advances head)\n  int v;\n  buffer.try_pop(v);\n  buffer.try_pop(v);\n\n  // Now push a batch that will wrap around\n  std::vector<int> items = {10, 11, 12, 13};\n  size_t pushed = buffer.try_push_batch(items.begin(), items.end());\n\n  EXPECT_EQ(pushed, 3u); // Only 3 slots available\n  EXPECT_TRUE(buffer.full());\n\n  // Pop all and verify order\n  std::vector<int> dest(4);\n  size_t popped = buffer.try_pop_batch(dest.begin(), 4);\n\n  EXPECT_EQ(popped, 4u);\n  EXPECT_EQ(dest[0], 2); // Remaining from initial push\n  EXPECT_EQ(dest[1], 10);\n  EXPECT_EQ(dest[2], 11);\n  EXPECT_EQ(dest[3], 12);\n}\n\nTEST(SPSCRingBuffer, BatchConcurrent) {\n  SPSCRingBuffer<int, 64> buffer;\n  constexpr int kNumItems = 100000;\n  constexpr int kBatchSize = 16;\n\n  std::atomic<bool> producerDone{false};\n  std::vector<int> consumed;\n  consumed.reserve(kNumItems);\n\n  std::thread producer([&]() {\n    std::vector<int> batch(kBatchSize);\n    for (int i = 0; i < kNumItems; i += kBatchSize) {\n      int batchEnd = std::min(i + kBatchSize, kNumItems);\n      for (int j = i; j < batchEnd; ++j) {\n        batch[j - i] = j;\n      }\n      size_t remaining = batchEnd - i;\n      auto it = batch.begin();\n      while (remaining > 0) {\n        size_t pushed = buffer.try_push_batch(it, it + remaining);\n        it += pushed;\n        remaining -= pushed;\n        if (remaining > 0) {\n          std::this_thread::yield();\n        }\n      }\n    }\n    producerDone.store(true, std::memory_order_release);\n  });\n\n  std::thread consumer([&]() {\n    std::vector<int> batch(kBatchSize);\n    while (consumed.size() < static_cast<size_t>(kNumItems)) {\n      size_t popped = buffer.try_pop_batch(batch.begin(), kBatchSize);\n      if (popped > 0) {\n        for (size_t i = 0; i < popped; ++i) {\n          consumed.push_back(batch[i]);\n        }\n      } else if (producerDone.load(std::memory_order_acquire) && buffer.empty()) {\n        break;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  producer.join();\n  consumer.join();\n\n  ASSERT_EQ(consumed.size(), kNumItems);\n  for (int i = 0; i < kNumItems; ++i) {\n    EXPECT_EQ(consumed[i], i) << \"Mismatch at index \" << i;\n  }\n}\n\n// =============================================================================\n// Stress Tests\n// =============================================================================\n\nTEST(SPSCRingBuffer, StressTest) {\n  SPSCRingBuffer<int, 64> buffer;\n  constexpr int kNumItems = 1000000;\n\n  std::atomic<int64_t> consumedSum{0};\n\n  std::thread producer([&]() {\n    for (int i = 1; i <= kNumItems; ++i) {\n      while (!buffer.try_push(i)) {\n        std::this_thread::yield();\n      }\n    }\n  });\n\n  std::thread consumer([&]() {\n    int64_t localSum = 0;\n    int count = 0;\n    while (count < kNumItems) {\n      int value;\n      if (buffer.try_pop(value)) {\n        localSum += value;\n        ++count;\n      } else {\n        std::this_thread::yield();\n      }\n    }\n    consumedSum.store(localSum, std::memory_order_relaxed);\n  });\n\n  producer.join();\n  consumer.join();\n\n  // Sum of 1 to N = N*(N+1)/2\n  int64_t expectedSum = static_cast<int64_t>(kNumItems) * (kNumItems + 1) / 2;\n  EXPECT_EQ(consumedSum.load(), expectedSum);\n}\n"
  },
  {
    "path": "tests/task_set_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/task_set.h>\n\n#include <atomic>\n#include <thread>\n#include <vector>\n\n#include <gtest/gtest.h>\n\n// Add a shim to account for older gtest\n#if !defined INSTANTIATE_TEST_SUITE_P\n#define INSTANTIATE_TEST_SUITE_P INSTANTIATE_TEST_CASE_P\n#endif // INSTANTIATE_TEST_CASE_P\n\nenum ScheduleType { kDefault, kForceQueue, kMixed };\n\nclass TaskSetTest : public ::testing::TestWithParam<ScheduleType> {\n protected:\n  void SetUp() override {}\n  void TearDown() override {}\n\n  template <typename TaskSetT, typename F>\n  void schedule(TaskSetT& taskSet, F&& f) {\n    switch (GetParam()) {\n      case kDefault:\n        taskSet.schedule(std::forward<F>(f));\n        break;\n      case kForceQueue:\n        taskSet.schedule(std::forward<F>(f), dispenso::ForceQueuingTag());\n        break;\n      case kMixed:\n        if (count_++ & 1) {\n          taskSet.schedule(std::forward<F>(f));\n        } else {\n          taskSet.schedule(std::forward<F>(f), dispenso::ForceQueuingTag());\n        }\n        break;\n    }\n  }\n\n private:\n  size_t count_ = 0;\n};\n\nINSTANTIATE_TEST_SUITE_P(\n    TaskSetTestParameters,\n    TaskSetTest,\n    testing::Values(kDefault, kForceQueue, kMixed));\n\nTEST_P(TaskSetTest, MixedWork) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet taskSet(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& a = outputsA[i];\n    auto& b = outputsB[i];\n    schedule(taskSet, [i, &a]() { a = i * i; });\n    schedule(taskSet, [i, &b]() { b = i * i * i; });\n  }\n\n  taskSet.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i * i);\n    EXPECT_EQ(outputsB[i], i * i * i);\n  }\n}\n\nTEST_P(TaskSetTest, MultiWait) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet taskSet(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& a = outputsA[i];\n    auto& b = outputsB[i];\n    schedule(taskSet, [i, &a]() { a = i * i; });\n    schedule(taskSet, [i, &b]() { b = i * i * i; });\n  }\n\n  taskSet.wait();\n\n  std::vector<int64_t> outputsC(kWorkItems, 0);\n  std::vector<int64_t> outputsD(kWorkItems, 0);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& c = outputsC[i];\n    auto& d = outputsD[i];\n    schedule(taskSet, [i, &c]() { c = static_cast<int64_t>(i * i - 5); });\n    schedule(taskSet, [i, &d]() { d = static_cast<int64_t>(i * i * i - 5); });\n  }\n\n  taskSet.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i * i);\n    EXPECT_EQ(outputsB[i], i * i * i);\n    EXPECT_EQ(outputsC[i], i * i - 5);\n    EXPECT_EQ(outputsD[i], i * i * i - 5);\n  }\n}\n\nTEST_P(TaskSetTest, MultiSet) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet taskSetA(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& a = outputsA[i];\n    auto& b = outputsB[i];\n    schedule(taskSetA, [i, &a]() { a = i * i; });\n    schedule(taskSetA, [i, &b]() { b = i * i * i; });\n  }\n\n  std::vector<int64_t> outputsC(kWorkItems, 0);\n  std::vector<int64_t> outputsD(kWorkItems, 0);\n  dispenso::TaskSet taskSetB(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& c = outputsC[i];\n    auto& d = outputsD[i];\n    schedule(taskSetB, [i, &c]() { c = static_cast<int64_t>(i * i - 5); });\n    schedule(taskSetB, [i, &d]() { d = static_cast<int64_t>(i * i * i - 5); });\n  }\n\n  taskSetA.wait();\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i * i);\n    EXPECT_EQ(outputsB[i], i * i * i);\n  }\n\n  taskSetB.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsC[i], i * i - 5);\n    EXPECT_EQ(outputsD[i], i * i * i - 5);\n  }\n}\n\nTEST_P(TaskSetTest, MultiSetTryWait) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet taskSetA(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& a = outputsA[i];\n    auto& b = outputsB[i];\n    schedule(taskSetA, [i, &a]() { a = i * i; });\n    schedule(taskSetA, [i, &b]() { b = i * i * i; });\n    (void)taskSetA.tryWait(1);\n  }\n\n  std::vector<int64_t> outputsC(kWorkItems, 0);\n  std::vector<int64_t> outputsD(kWorkItems, 0);\n  dispenso::TaskSet taskSetB(pool);\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    auto& c = outputsC[i];\n    auto& d = outputsD[i];\n    schedule(taskSetB, [i, &c]() { c = static_cast<int64_t>(i * i - 5); });\n    schedule(taskSetB, [i, &d]() { d = static_cast<int64_t>(i * i * i - 5); });\n    (void)taskSetB.tryWait(1);\n  }\n\n  while (!taskSetA.tryWait(1)) {\n  }\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i * i);\n    EXPECT_EQ(outputsB[i], i * i * i);\n  }\n\n  taskSetB.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsC[i], i * i - 5);\n    EXPECT_EQ(outputsD[i], i * i * i - 5);\n  }\n}\n\nTEST(TaskSetTest, ParamConstruction) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet taskSetA(pool);\n  dispenso::TaskSet taskSetB(pool, 4);\n  dispenso::TaskSet taskSetC(pool, dispenso::ParentCascadeCancel::kOn);\n  dispenso::TaskSet taskSetD(pool, dispenso::ParentCascadeCancel::kOff, 4);\n}\n\nTEST(ConcurrentTaskSetTest, ParamConstruction) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet taskSetA(pool);\n  dispenso::ConcurrentTaskSet taskSetB(pool, 4);\n  dispenso::ConcurrentTaskSet taskSetC(pool, dispenso::ParentCascadeCancel::kOn);\n  dispenso::ConcurrentTaskSet taskSetD(pool, dispenso::ParentCascadeCancel::kOff, 4);\n}\n\nstatic void recursiveFunc(dispenso::ThreadPool& pool, int num) {\n  if (num <= 0)\n    return;\n  std::atomic<int> value(0);\n  dispenso::TaskSet taskSet(pool);\n  for (int i = 0; i < num; ++i) {\n    taskSet.schedule([i, &value, &pool]() {\n      recursiveFunc(pool, i - 1);\n      ++value;\n    });\n  }\n  taskSet.wait();\n  EXPECT_EQ(value.load(), num);\n}\n\nTEST(TaskSet, Recursive) {\n  dispenso::ThreadPool pool(10);\n  recursiveFunc(pool, 20);\n}\n\nstruct Node {\n  int val;\n  std::unique_ptr<Node> left, right;\n};\n\nstatic void buildTree(dispenso::ConcurrentTaskSet& tasks, std::unique_ptr<Node>& node, int depth) {\n  if (depth) {\n    node = std::make_unique<Node>();\n    node->val = depth;\n    tasks.schedule([&tasks, &left = node->left, depth]() { buildTree(tasks, left, depth - 1); });\n    tasks.schedule([&tasks, &right = node->right, depth]() { buildTree(tasks, right, depth - 1); });\n  }\n}\n\nstatic void verifyTree(const std::unique_ptr<Node>& node, int depthRemaining) {\n  if (depthRemaining) {\n    ASSERT_EQ(node->val, depthRemaining);\n    verifyTree(node->left, depthRemaining - 1);\n    verifyTree(node->right, depthRemaining - 1);\n  }\n}\n\nTEST(ConcurrentTaskSet, DoTree) {\n  std::unique_ptr<Node> root;\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n  buildTree(tasks, root, 20);\n  tasks.wait();\n  verifyTree(root, 20);\n}\n\nTEST(TaskSet, OneChildCancels) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.schedule(\n      []() {\n        while (!dispenso::parentTaskSet()->canceled())\n          ;\n      },\n      dispenso::ForceQueuingTag());\n\n  tasks.schedule([]() { dispenso::parentTaskSet()->cancel(); }, dispenso::ForceQueuingTag());\n  EXPECT_TRUE(tasks.wait());\n}\n\nTEST(TaskSet, ParentThreadCancels) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.schedule(\n      []() {\n        while (!dispenso::parentTaskSet()->canceled())\n          ;\n      },\n      dispenso::ForceQueuingTag());\n\n  tasks.cancel();\n  EXPECT_TRUE(tasks.wait());\n}\n\nTEST(TaskSet, CascadingCancelOne) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.schedule(\n      [&pool]() {\n        dispenso::TaskSet tasks2(pool, dispenso::ParentCascadeCancel::kOn);\n        tasks2.schedule([]() {\n          while (!dispenso::parentTaskSet()->canceled())\n            ;\n        });\n      },\n      dispenso::ForceQueuingTag());\n\n  tasks.cancel();\n  EXPECT_TRUE(tasks.wait());\n}\n\nTEST(TaskSet, CascadingOne) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int a = 5;\n\n  tasks.schedule(\n      [&pool, &a]() {\n        dispenso::TaskSet tasks2(pool);\n        tasks2.schedule([&a]() { a = 7; });\n      },\n      dispenso::ForceQueuingTag());\n\n  EXPECT_FALSE(tasks.wait());\n  EXPECT_EQ(a, 7);\n}\n\nTEST(TaskSet, CascadingManyCancel) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  // Use nonconst instead of constexpr to avoid older MSVC error\n  size_t kBranchFactor = 200;\n\n  std::vector<size_t> values(kBranchFactor * kBranchFactor);\n\n  for (size_t i = 0; i < kBranchFactor; ++i) {\n    tasks.schedule(\n        [&pool, kBranchFactor]() {\n          dispenso::TaskSet tasks2(pool, dispenso::ParentCascadeCancel::kOn);\n          for (size_t j = 0; j < kBranchFactor; ++j) {\n            tasks2.schedule([]() {\n              while (!dispenso::parentTaskSet()->canceled()) {\n              }\n            });\n          }\n        },\n        dispenso::ForceQueuingTag());\n  }\n\n  std::this_thread::sleep_for(std::chrono::milliseconds(10));\n  tasks.cancel();\n\n  EXPECT_TRUE(tasks.wait());\n}\n\nTEST(TaskSet, CascadingMany) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  // Use nonconst instead of constexpr to avoid older MSVC error\n  size_t kBranchFactor = 200;\n\n  std::vector<size_t> values(kBranchFactor * kBranchFactor);\n\n  for (size_t i = 0; i < kBranchFactor; ++i) {\n    tasks.schedule(\n        [&pool, &values, i, kBranchFactor]() {\n          dispenso::TaskSet tasks2(pool);\n          for (size_t j = 0; j < kBranchFactor; ++j) {\n            tasks2.schedule(\n                [&values, i, j, kBranchFactor]() { values[i * kBranchFactor + j] = i + j; });\n          }\n        },\n        dispenso::ForceQueuingTag());\n  }\n  EXPECT_FALSE(tasks.wait());\n  for (size_t i = 0; i < kBranchFactor; ++i) {\n    for (size_t j = 0; j < kBranchFactor; ++j) {\n      EXPECT_EQ(i + j, values[i * kBranchFactor + j]);\n    }\n  }\n}\n\n#if defined(__cpp_exceptions)\nTEST(TaskSet, Exception) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); }, dispenso::ForceQueuingTag());\n\n  bool caught = false;\n  try {\n    tasks.wait();\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(ConcurrentTaskSet, Exception) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); }, dispenso::ForceQueuingTag());\n\n  bool caught = false;\n  try {\n    tasks.wait();\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(TaskSet, ExceptionNoForceQueuing) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); });\n\n  bool caught = false;\n  try {\n    tasks.wait();\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(ConcurrentTaskSet, ExceptionNoForceQueuing) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); });\n\n  bool caught = false;\n  try {\n    tasks.wait();\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(TaskSet, ExceptionTryWait) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int data = 32767;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); }, dispenso::ForceQueuingTag());\n\n  bool caught = false;\n  try {\n    while (!tasks.tryWait(1)) {\n    }\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(ConcurrentTaskSet, ExceptionTryWait) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); }, dispenso::ForceQueuingTag());\n\n  bool caught = false;\n  try {\n    while (!tasks.tryWait(1)) {\n    }\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(TaskSet, ExceptionNoForceQueuingTryWait) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); });\n\n  bool caught = false;\n  try {\n    while (!tasks.tryWait(1)) {\n    }\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(ConcurrentTaskSet, ExceptionNoForceQueuingTryWait) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); });\n\n  bool caught = false;\n  try {\n    while (!tasks.tryWait(1)) {\n    }\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\nTEST(TaskSet, ExceptionCancels) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  int data = 3;\n\n  tasks.schedule(\n      []() {\n        while (!dispenso::parentTaskSet()->canceled())\n          ;\n      },\n      dispenso::ForceQueuingTag());\n\n  tasks.schedule([]() { throw std::logic_error(\"oops\"); }, dispenso::ForceQueuingTag());\n\n  bool caught = false;\n  try {\n    tasks.wait();\n    EXPECT_EQ(data, 12);\n  } catch (...) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n\n#endif // __cpp_exceptions\n\nTEST(TaskSet, EmptyTaskSet) {\n  // Test that an empty TaskSet can be waited on without issues\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n\n  // wait() on empty TaskSet should return immediately with no cancellation\n  EXPECT_FALSE(tasks.wait());\n\n  // Should be able to reuse after empty wait\n  std::atomic<int> counter{0};\n  tasks.schedule([&counter]() { counter.fetch_add(1); });\n  EXPECT_FALSE(tasks.wait());\n  EXPECT_EQ(counter.load(), 1);\n}\n\nTEST(TaskSet, TryWaitOnEmpty) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n\n  // tryWait on empty TaskSet should return true immediately\n  EXPECT_TRUE(tasks.tryWait(0));\n  EXPECT_TRUE(tasks.tryWait(1));\n  EXPECT_TRUE(tasks.tryWait(100));\n}\n\nTEST(TaskSet, CanceledStateBeforeCancellation) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n\n  // Before any cancellation, canceled() should return false\n  EXPECT_FALSE(tasks.canceled());\n\n  std::atomic<bool> sawNotCanceled{false};\n  tasks.schedule([&sawNotCanceled]() {\n    if (dispenso::parentTaskSet() && !dispenso::parentTaskSet()->canceled()) {\n      sawNotCanceled.store(true);\n    }\n  });\n\n  tasks.wait();\n  EXPECT_TRUE(sawNotCanceled.load());\n  EXPECT_FALSE(tasks.canceled());\n}\n\nTEST(TaskSet, SingleTask) {\n  dispenso::ThreadPool pool(4);\n  dispenso::TaskSet tasks(pool);\n\n  int result = 0;\n  tasks.schedule([&result]() { result = 42; });\n  tasks.wait();\n\n  EXPECT_EQ(result, 42);\n}\n\nTEST(TaskSet, GlobalThreadPool) {\n  // Explicitly test with globalThreadPool()\n  dispenso::TaskSet tasks(dispenso::globalThreadPool());\n\n  std::atomic<int> sum{0};\n  for (int i = 0; i < 100; ++i) {\n    tasks.schedule([&sum, i]() { sum.fetch_add(i); });\n  }\n  tasks.wait();\n\n  // Sum of 0..99 = 4950\n  EXPECT_EQ(sum.load(), 4950);\n}\n\nTEST(ConcurrentTaskSet, EmptyTaskSet) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  // wait() on empty ConcurrentTaskSet should return immediately\n  EXPECT_FALSE(tasks.wait());\n}\n\nTEST(ConcurrentTaskSet, TryWaitOnEmpty) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  EXPECT_TRUE(tasks.tryWait(0));\n  EXPECT_TRUE(tasks.tryWait(1));\n}\n\nTEST(ConcurrentTaskSet, ConcurrentScheduling) {\n  // Test that multiple threads can schedule to a ConcurrentTaskSet simultaneously\n  dispenso::ThreadPool pool(8);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  std::atomic<int> counter{0};\n  static constexpr int kTasksPerThread = 100;\n  static constexpr int kNumSchedulers = 4;\n\n  // Create threads that will concurrently schedule tasks\n  std::vector<std::thread> schedulers;\n  for (int t = 0; t < kNumSchedulers; ++t) {\n    schedulers.emplace_back([&]() {\n      for (int i = 0; i < kTasksPerThread; ++i) {\n        tasks.schedule([&counter]() { counter.fetch_add(1); });\n      }\n    });\n  }\n\n  // Wait for all schedulers to finish\n  for (auto& t : schedulers) {\n    t.join();\n  }\n\n  // Wait for all tasks to complete\n  tasks.wait();\n\n  EXPECT_EQ(counter.load(), kTasksPerThread * kNumSchedulers);\n}\n\nTEST(TaskSet, LargeBatchOfTasks) {\n  dispenso::ThreadPool pool(8);\n  dispenso::TaskSet tasks(pool);\n\n  constexpr int kNumTasks = 10000;\n  std::vector<int> results(kNumTasks, 0);\n\n  for (int i = 0; i < kNumTasks; ++i) {\n    tasks.schedule([&results, i]() { results[static_cast<size_t>(i)] = i * i; });\n  }\n\n  tasks.wait();\n\n  for (int i = 0; i < kNumTasks; ++i) {\n    EXPECT_EQ(results[static_cast<size_t>(i)], i * i);\n  }\n}\n\nTEST(ConcurrentTaskSet, CanceledState) {\n  dispenso::ThreadPool pool(4);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  EXPECT_FALSE(tasks.canceled());\n\n  tasks.schedule(\n      []() {\n        while (!dispenso::parentTaskSet()->canceled()) {\n          std::this_thread::yield();\n        }\n      },\n      dispenso::ForceQueuingTag());\n\n  // Give the task time to start\n  std::this_thread::sleep_for(std::chrono::milliseconds(1));\n\n  tasks.cancel();\n  EXPECT_TRUE(tasks.canceled());\n  EXPECT_TRUE(tasks.wait());\n}\n\nTEST(TaskSet, ScheduleBulkBasic) {\n  constexpr size_t kWorkItems = 1000;\n  std::vector<size_t> outputs(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.scheduleBulk(\n      kWorkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i * i; }; });\n\n  tasks.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[i], i * i);\n  }\n}\n\nTEST(TaskSet, ScheduleBulkEdgeCases) {\n  dispenso::ThreadPool pool(10);\n\n  // Count=0: no-op\n  {\n    dispenso::TaskSet tasks(pool);\n    bool called = false;\n    tasks.scheduleBulk(0, [&called](size_t) {\n      called = true;\n      return []() {};\n    });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_FALSE(called);\n  }\n\n  // Count=1: single task\n  {\n    dispenso::TaskSet tasks(pool);\n    int result = 0;\n    tasks.scheduleBulk(\n        1, [&result](size_t i) { return [i, &result]() { result = static_cast<int>(i) + 42; }; });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_EQ(result, 42);\n  }\n\n  // Count=2: two tasks\n  {\n    dispenso::TaskSet tasks(pool);\n    std::vector<int> outputs(2, 0);\n    tasks.scheduleBulk(2, [&outputs](size_t i) {\n      return [i, &outputs]() { outputs[i] = static_cast<int>(i) + 1; };\n    });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_EQ(outputs[0], 1);\n    EXPECT_EQ(outputs[1], 2);\n  }\n}\n\nTEST(TaskSet, ScheduleBulkLarge) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputs(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.scheduleBulk(\n      kWorkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i * i; }; });\n\n  tasks.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[i], i * i);\n  }\n}\n\nTEST(TaskSet, ScheduleBulkMultipleWaits) {\n  constexpr size_t kWorkItems = 1000;\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  tasks.scheduleBulk(\n      kWorkItems, [&outputsA](size_t i) { return [i, &outputsA]() { outputsA[i] = i + 1; }; });\n  tasks.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i + 1);\n  }\n\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  tasks.scheduleBulk(\n      kWorkItems, [&outputsB](size_t i) { return [i, &outputsB]() { outputsB[i] = i * 2; }; });\n  tasks.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsB[i], i * 2);\n  }\n}\n\nTEST(TaskSet, ScheduleBulkMixedWithSchedule) {\n  static constexpr size_t kBulkItems = 500;\n  static constexpr size_t kScheduleItems = 500;\n  static constexpr size_t kTotal = kBulkItems + kScheduleItems + kBulkItems;\n  std::vector<size_t> outputs(kTotal, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  // First bulk batch\n  tasks.scheduleBulk(\n      kBulkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i + 1; }; });\n\n  // Individual schedule\n  for (size_t i = kBulkItems; i < kBulkItems + kScheduleItems; ++i) {\n    tasks.schedule([i, &outputs]() { outputs[i] = i + 1; });\n  }\n\n  // Second bulk batch\n  tasks.scheduleBulk(kBulkItems, [&outputs](size_t i) {\n    size_t idx = i + kBulkItems + kScheduleItems;\n    return [idx, &outputs]() { outputs[idx] = idx + 1; };\n  });\n\n  tasks.wait();\n\n  for (size_t i = 0; i < kTotal; ++i) {\n    EXPECT_EQ(outputs[i], i + 1);\n  }\n}\n\nTEST(TaskSet, ScheduleBulkCancellation) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  // Schedule spinning tasks via individual schedule with ForceQueuingTag\n  // to ensure they land on pool threads\n  for (int i = 0; i < 4; ++i) {\n    tasks.schedule(\n        []() {\n          while (!dispenso::parentTaskSet()->canceled()) {\n            std::this_thread::yield();\n          }\n        },\n        dispenso::ForceQueuingTag());\n  }\n\n  // Bulk-schedule more work\n  std::vector<int> outputs(100, 0);\n  tasks.scheduleBulk(100, [&outputs](size_t i) {\n    return [i, &outputs]() { outputs[i] = static_cast<int>(i) + 1; };\n  });\n\n  tasks.cancel();\n  EXPECT_TRUE(tasks.wait());\n}\n\n#if defined(__cpp_exceptions)\nTEST(TaskSet, ScheduleBulkException) {\n  dispenso::ThreadPool pool(10);\n  dispenso::TaskSet tasks(pool);\n\n  tasks.scheduleBulk(100, [](size_t i) {\n    return [i]() {\n      if (i == 50) {\n        throw std::logic_error(\"bulk oops\");\n      }\n    };\n  });\n\n  bool caught = false;\n  try {\n    tasks.wait();\n  } catch (const std::logic_error&) {\n    caught = true;\n  }\n\n  EXPECT_TRUE(caught);\n}\n#endif // __cpp_exceptions\n\nTEST(ConcurrentTaskSet, ScheduleBulkBasic) {\n  constexpr size_t kWorkItems = 1000;\n  std::vector<size_t> outputs(kWorkItems, 0);\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  tasks.scheduleBulk(\n      kWorkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i * i; }; });\n\n  tasks.wait();\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[i], i * i);\n  }\n}\n\nTEST(ConcurrentTaskSet, ScheduleBulkEdgeCases) {\n  dispenso::ThreadPool pool(10);\n\n  // Count=0: no-op\n  {\n    dispenso::ConcurrentTaskSet tasks(pool);\n    bool called = false;\n    tasks.scheduleBulk(0, [&called](size_t) {\n      called = true;\n      return []() {};\n    });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_FALSE(called);\n  }\n\n  // Count=1: single task\n  {\n    dispenso::ConcurrentTaskSet tasks(pool);\n    std::atomic<int> result{0};\n    tasks.scheduleBulk(1, [&result](size_t i) {\n      return [i, &result]() { result.store(static_cast<int>(i) + 42); };\n    });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_EQ(result.load(), 42);\n  }\n\n  // Count=2: two tasks\n  {\n    dispenso::ConcurrentTaskSet tasks(pool);\n    std::atomic<int> count{0};\n    tasks.scheduleBulk(2, [&count](size_t) { return [&count]() { count.fetch_add(1); }; });\n    EXPECT_FALSE(tasks.wait());\n    EXPECT_EQ(count.load(), 2);\n  }\n}\n\nTEST(ConcurrentTaskSet, ScheduleBulkConcurrent) {\n  static constexpr int kTasksPerThread = 100;\n  static constexpr int kNumSchedulers = 4;\n  std::atomic<int> counter{0};\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  std::vector<std::thread> schedulers;\n  for (int t = 0; t < kNumSchedulers; ++t) {\n    schedulers.emplace_back([&tasks, &counter]() {\n      tasks.scheduleBulk(static_cast<size_t>(kTasksPerThread), [&counter](size_t) {\n        return [&counter]() { counter.fetch_add(1, std::memory_order_relaxed); };\n      });\n    });\n  }\n\n  for (auto& t : schedulers) {\n    t.join();\n  }\n\n  tasks.wait();\n  EXPECT_EQ(counter.load(), kTasksPerThread * kNumSchedulers);\n}\n\nTEST(ConcurrentTaskSet, ScheduleBulkMixedWithSchedule) {\n  static constexpr size_t kBulkItems = 500;\n  static constexpr size_t kScheduleItems = 500;\n  static constexpr size_t kTotal = kBulkItems + kScheduleItems + kBulkItems;\n  std::vector<std::atomic<int>> outputs(kTotal);\n  for (auto& o : outputs) {\n    o.store(0);\n  }\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  // First bulk batch\n  tasks.scheduleBulk(kBulkItems, [&outputs](size_t i) {\n    return [i, &outputs]() { outputs[i].store(static_cast<int>(i) + 1); };\n  });\n\n  // Individual schedule\n  for (size_t i = kBulkItems; i < kBulkItems + kScheduleItems; ++i) {\n    tasks.schedule([i, &outputs]() { outputs[i].store(static_cast<int>(i) + 1); });\n  }\n\n  // Second bulk batch\n  tasks.scheduleBulk(kBulkItems, [&outputs](size_t i) {\n    size_t idx = i + kBulkItems + kScheduleItems;\n    return [idx, &outputs]() { outputs[idx].store(static_cast<int>(idx) + 1); };\n  });\n\n  tasks.wait();\n\n  for (size_t i = 0; i < kTotal; ++i) {\n    EXPECT_EQ(outputs[i].load(), static_cast<int>(i) + 1);\n  }\n}\n\nTEST(ConcurrentTaskSet, ScheduleBulkCancellation) {\n  dispenso::ThreadPool pool(10);\n  dispenso::ConcurrentTaskSet tasks(pool);\n\n  // Schedule spinning tasks via individual schedule with ForceQueuingTag\n  for (int i = 0; i < 4; ++i) {\n    tasks.schedule(\n        []() {\n          while (!dispenso::parentTaskSet()->canceled()) {\n            std::this_thread::yield();\n          }\n        },\n        dispenso::ForceQueuingTag());\n  }\n\n  // Bulk-schedule more work\n  std::atomic<int> bulkCounter{0};\n  tasks.scheduleBulk(\n      100, [&bulkCounter](size_t) { return [&bulkCounter]() { bulkCounter.fetch_add(1); }; });\n\n  tasks.cancel();\n  EXPECT_TRUE(tasks.wait());\n}\n"
  },
  {
    "path": "tests/test_tid.h",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#pragma once\n\n#include <dispenso/platform.h>\n\n// Note that this header is intended for direct inclusion into test cpps that require the\n// functionality.  tids are essentially independent for tranlation units (don't expect\n// coordinated/sane behavior if used from multiple cpps in the same binary).\n\nnamespace {\n\nstd::atomic<int> g_nextTid(0);\nDISPENSO_THREAD_LOCAL int g_tid = -1;\n\ninline void resetTestTid() {\n  g_tid = -1;\n  g_nextTid.store(0);\n}\n\ninline int getTestTid() {\n  if (g_tid < 0) {\n    g_tid = g_nextTid.fetch_add(1, std::memory_order_relaxed);\n  }\n  return g_tid;\n}\n\n} // namespace\n"
  },
  {
    "path": "tests/thread_id_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/thread_id.h>\n\n#include <unordered_set>\n#include <vector>\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\nTEST(ThreadId, Repeatable) {\n  constexpr int kRounds = 100;\n  constexpr int kThreadsPerRound = 8;\n  for (int round = 0; round < kRounds; ++round) {\n    std::vector<std::thread> threads;\n    for (int i = 0; i < kThreadsPerRound; ++i) {\n      threads.emplace_back([]() {\n        constexpr int kTrials = 1000;\n        auto id = dispenso::threadId();\n\n        for (int i = 0; i < kTrials; ++i) {\n          EXPECT_EQ(id, dispenso::threadId());\n        }\n      });\n    }\n\n    for (auto& t : threads) {\n      t.join();\n    }\n  }\n}\n\nTEST(ThreadId, Unique) {\n  constexpr int kRounds = 1000;\n  constexpr int kThreadsPerRound = 8;\n\n  std::vector<uint64_t> ids(kRounds * kThreadsPerRound);\n  std::atomic<size_t> slot(0);\n\n  for (int round = 0; round < kRounds; ++round) {\n    std::vector<std::thread> threads;\n    for (int i = 0; i < kThreadsPerRound; ++i) {\n      threads.emplace_back([&ids, &slot]() {\n        ids[slot.fetch_add(1, std::memory_order_relaxed)] = dispenso::threadId();\n      });\n    }\n\n    for (auto& t : threads) {\n      t.join();\n    }\n  }\n\n  std::unordered_set<uint64_t> uniquenessSet;\n  for (uint64_t id : ids) {\n    EXPECT_TRUE(uniquenessSet.insert(id).second);\n  }\n}\n"
  },
  {
    "path": "tests/thread_pool_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/thread_pool.h>\n\n#include <atomic>\n#include <thread>\n#include <vector>\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n// Add a shim to account for older gtest\n#if !defined INSTANTIATE_TEST_SUITE_P\n#define INSTANTIATE_TEST_SUITE_P INSTANTIATE_TEST_CASE_P\n#endif // INSTANTIATE_TEST_CASE_P\n\nusing testing::AnyOf;\nusing testing::Eq;\n\nTEST(ThreadPool, SimpleCreationDestruction) {\n  dispenso::ThreadPool pool(10);\n  EXPECT_EQ(pool.numThreads(), 10);\n}\n\nTEST(ThreadPool, Resize) {\n  dispenso::ThreadPool pool(10);\n  EXPECT_EQ(10, pool.numThreads());\n  pool.resize(8);\n  EXPECT_EQ(8, pool.numThreads());\n  pool.resize(12);\n  EXPECT_EQ(12, pool.numThreads());\n  pool.resize(12);\n  EXPECT_EQ(12, pool.numThreads());\n}\n\nenum ScheduleType { kDefault, kForceQueue, kMixed };\n\nclass ThreadPoolTest : public testing::TestWithParam<ScheduleType> {\n protected:\n  void initPool(size_t threads) {\n    pool_ = std::make_unique<dispenso::ThreadPool>(threads);\n  }\n\n  template <typename F>\n  void schedule(F&& f) {\n    switch (GetParam()) {\n      case kDefault:\n        pool_->schedule(std::forward<F>(f));\n        break;\n      case kForceQueue:\n        pool_->schedule(std::forward<F>(f), dispenso::ForceQueuingTag());\n        break;\n      case kMixed:\n        if (count_++ & 1) {\n          pool_->schedule(std::forward<F>(f));\n        } else {\n          pool_->schedule(std::forward<F>(f), dispenso::ForceQueuingTag());\n        }\n        break;\n    }\n  }\n\n  void destroyPool() {\n    pool_.reset();\n  }\n\n protected:\n  std::unique_ptr<dispenso::ThreadPool> pool_;\n  size_t count_ = 0;\n};\n\nINSTANTIATE_TEST_SUITE_P(\n    ThreadPoolTestParameters,\n    ThreadPoolTest,\n    testing::Values(kDefault, kForceQueue, kMixed));\n\nTEST_P(ThreadPoolTest, SimpleWork) {\n  constexpr int kWorkItems = 10000;\n  std::vector<int> outputs(kWorkItems, 0);\n  {\n    initPool(10);\n    int i = 0;\n    for (int& o : outputs) {\n      schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    destroyPool();\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST_P(ThreadPoolTest, MixedWork) {\n  constexpr size_t kWorkItems = 10000;\n  std::vector<size_t> outputsA(kWorkItems, 0);\n  std::vector<size_t> outputsB(kWorkItems, 0);\n  {\n    initPool(10);\n    for (size_t i = 0; i < kWorkItems; ++i) {\n      auto& a = outputsA[i];\n      auto& b = outputsB[i];\n      schedule([i, &a]() { a = i * i; });\n      schedule([i, &b]() { b = i * i * i; });\n    }\n    destroyPool();\n  }\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputsA[i], i * i);\n    EXPECT_EQ(outputsB[i], i * i * i);\n  }\n}\n\nTEST(ThreadPool, ResizeConcurrent) {\n  constexpr int kWorkItems = 10000;\n  std::vector<int> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n    int i = 0;\n    for (int& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n\n      if ((i & 127) == 0) {\n        if (pool.numThreads() == 1) {\n          pool.resize(10);\n        }\n        pool.resize(pool.numThreads() - 1);\n      }\n    }\n    EXPECT_EQ(4, pool.numThreads());\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, ResizeMoreConcurrent) {\n  constexpr int kWorkItems = 1000000;\n  std::vector<int64_t> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n\n    std::thread resizer0([&pool]() {\n      for (int i = 0; i < 2000; ++i) {\n        pool.resize(4);\n      }\n    });\n\n    std::thread resizer1([&pool]() {\n      for (int i = 0; i < 2000; ++i) {\n        pool.resize(8);\n      }\n    });\n\n    int64_t i = 0;\n    for (int64_t& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    resizer0.join();\n    resizer1.join();\n\n    EXPECT_THAT(static_cast<int>(pool.numThreads()), AnyOf(Eq(4), Eq(8)));\n  }\n\n  int64_t i = 0;\n  for (int64_t o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, SetSignalingWakeConcurrent) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 1000000;\n  std::vector<int64_t> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n\n    std::thread resetter0([&pool]() {\n      for (int i = 0; i < 100; ++i) {\n        pool.setSignalingWake(true, 1000us);\n      }\n    });\n\n    std::thread resetter1([&pool]() {\n      for (int i = 0; i < 100; ++i) {\n        pool.setSignalingWake(false, 400us);\n      }\n    });\n\n    int64_t i = 0;\n    for (int64_t& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    resetter0.join();\n    resetter1.join();\n\n    EXPECT_EQ(static_cast<int>(pool.numThreads()), 10);\n  }\n\n  int64_t i = 0;\n  for (int64_t o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, ResizeCheckApproxActualRunningThreads) {\n  constexpr int kWorkItems = 1000000;\n  std::vector<int64_t> outputs(kWorkItems, 0);\n  std::atomic<int> completed(0);\n\n  std::mutex mtx;\n  std::set<std::thread::id> tidSet;\n\n  dispenso::ThreadPool pool(1);\n\n  pool.resize(8);\n\n  int64_t i = 0;\n  for (int64_t& o : outputs) {\n    pool.schedule([i, &o, &completed, &mtx, &tidSet]() {\n      o = i * i;\n      completed.fetch_add(1, std::memory_order_release);\n      std::lock_guard<std::mutex> lk(mtx);\n      tidSet.insert(std::this_thread::get_id());\n    });\n    ++i;\n  }\n\n  while (completed.load(std::memory_order_acquire) < kWorkItems) {\n  }\n\n  // We choose > 2 because there is 1 original thread, and one schedule thread (main thread). In\n  // order to not have an occasional flake, we choose much lower than 8, though this test is\n  // fundamentally flawed in that it cannot guarantee flake-free behavior.  Thus we turn this\n  // particular check off when running in TSAN.\n#if !DISPENSO_HAS_TSAN\n  EXPECT_GT(tidSet.size(), 2);\n#endif //! DISPENSO_HAS_TSAN\n\n  EXPECT_THAT(static_cast<int>(pool.numThreads()), AnyOf(Eq(4), Eq(8)));\n\n  i = 0;\n  for (int64_t o : outputs) {\n    EXPECT_EQ(o, i * i) << \" i = \" << i;\n    ++i;\n  }\n}\n\nTEST_P(ThreadPoolTest, CrossPoolTest) {\n  constexpr int kWorkItems = 10000;\n  std::vector<int> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool otherPool(8);\n    initPool(10);\n    int i = 0;\n    for (int& o : outputs) {\n      schedule([i, &o, &otherPool]() { otherPool.schedule([i, &o]() { o = i * i; }); });\n      ++i;\n    }\n    destroyPool();\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, SetSignalingWakeConcurrentZeroLatency) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 1000000;\n  std::vector<int64_t> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n\n    std::thread resetter0([&pool]() {\n      for (int i = 0; i < 100; ++i) {\n        pool.setSignalingWake(true, 0us);\n      }\n    });\n\n    std::thread resetter1([&pool]() {\n      for (int i = 0; i < 100; ++i) {\n        pool.setSignalingWake(false, 400us);\n      }\n    });\n\n    int64_t i = 0;\n    for (int64_t& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    resetter0.join();\n    resetter1.join();\n\n    EXPECT_EQ(static_cast<int>(pool.numThreads()), 10);\n  }\n\n  int64_t i = 0;\n  for (int64_t o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST_P(ThreadPoolTest, SimpleWorkZeroLatencyPoll) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 10000;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  int i;\n\n  {\n    initPool(10);\n    pool_->setSignalingWake(true, 0us);\n\n    i = 0;\n    for (int& o : outputs) {\n      schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    destroyPool();\n  }\n\n  i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n\n  // switch scheduling method\n\n  {\n    initPool(10);\n    pool_->setSignalingWake(false, 0us);\n\n    i = 0;\n    for (int& o : outputs) {\n      schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n    destroyPool();\n  }\n\n  i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\n// Tests for spin-poll with sleep mode (non-signaling wake)\n// This mode was the previous default before signaling wake became default\n\nTEST(ThreadPool, SpinPollWithSleep) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 1000;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  {\n    dispenso::ThreadPool pool(4);\n    // Enable spin-poll with sleep mode (non-signaling)\n    pool.setSignalingWake(false, 100us);\n\n    int i = 0;\n    for (int& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, SpinPollWithSleepForceQueue) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 1000;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  {\n    dispenso::ThreadPool pool(4);\n    pool.setSignalingWake(false, 200us);\n\n    int i = 0;\n    for (int& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; }, dispenso::ForceQueuingTag());\n      ++i;\n    }\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, SpinPollWithSleepResizeConcurrent) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 10000;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  {\n    dispenso::ThreadPool pool(8);\n    pool.setSignalingWake(false, 50us);\n\n    std::thread resizer([&pool]() {\n      for (int j = 0; j < 20; ++j) {\n        pool.resize(4);\n        std::this_thread::sleep_for(1ms);\n        pool.resize(8);\n        std::this_thread::sleep_for(1ms);\n      }\n    });\n\n    int i = 0;\n    for (int& o : outputs) {\n      pool.schedule([i, &o]() { o = i * i; });\n      ++i;\n    }\n\n    resizer.join();\n  }\n\n  int i = 0;\n  for (int o : outputs) {\n    EXPECT_EQ(o, i * i);\n    ++i;\n  }\n}\n\nTEST(ThreadPool, TransitionBetweenModes) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 500;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  dispenso::ThreadPool pool(4);\n\n  // Start in signaling wake mode (default)\n  int i = 0;\n  for (; i < kWorkItems / 3; ++i) {\n    pool.schedule([i, &outputs]() { outputs[static_cast<size_t>(i)] = i * 2; });\n  }\n\n  // Switch to spin-poll with sleep\n  pool.setSignalingWake(false, 100us);\n  for (; i < 2 * kWorkItems / 3; ++i) {\n    pool.schedule([i, &outputs]() { outputs[static_cast<size_t>(i)] = i * 2; });\n  }\n\n  // Switch back to signaling wake\n  pool.setSignalingWake(true, 100us);\n  for (; i < kWorkItems; ++i) {\n    pool.schedule([i, &outputs]() { outputs[static_cast<size_t>(i)] = i * 2; });\n  }\n\n  // Wait for completion by destroying pool\n  pool.resize(0);\n\n  for (i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[static_cast<size_t>(i)], i * 2);\n  }\n}\n\nTEST(ThreadPool, SpinPollWithDifferentSleepDurations) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 200;\n\n  for (auto sleepDur : {10us, 50us, 100us, 500us, 1000us}) {\n    std::vector<int> outputs(kWorkItems, 0);\n\n    {\n      dispenso::ThreadPool pool(4);\n      pool.setSignalingWake(false, sleepDur);\n\n      for (int i = 0; i < kWorkItems; ++i) {\n        pool.schedule([i, &outputs]() { outputs[static_cast<size_t>(i)] = i + 1; });\n      }\n    }\n\n    for (int i = 0; i < kWorkItems; ++i) {\n      EXPECT_EQ(outputs[static_cast<size_t>(i)], i + 1)\n          << \"Failed with sleep duration \" << sleepDur.count() << \"us\";\n    }\n  }\n}\n\nTEST(ThreadPool, SingleThreadSpinPoll) {\n  using namespace std::chrono_literals;\n  constexpr int kWorkItems = 100;\n  std::vector<int> outputs(kWorkItems, 0);\n\n  {\n    dispenso::ThreadPool pool(1);\n    pool.setSignalingWake(false, 100us);\n\n    for (int i = 0; i < kWorkItems; ++i) {\n      pool.schedule([i, &outputs]() { outputs[static_cast<size_t>(i)] = i * 3; });\n    }\n  }\n\n  for (int i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[static_cast<size_t>(i)], i * 3);\n  }\n}\n\nTEST(ThreadPool, ScheduleBulkBasic) {\n  constexpr size_t kWorkItems = 1000;\n  std::vector<size_t> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n    pool.scheduleBulk(\n        kWorkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i * i; }; });\n  }\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[i], i * i);\n  }\n}\n\nTEST(ThreadPool, ScheduleBulkZero) {\n  dispenso::ThreadPool pool(10);\n  bool called = false;\n  pool.scheduleBulk(0, [&called](size_t) {\n    called = true;\n    return []() {};\n  });\n  // Generator should never be called for count=0\n  EXPECT_FALSE(called);\n}\n\nTEST(ThreadPool, ScheduleBulkOne) {\n  std::atomic<int> result{0};\n  {\n    dispenso::ThreadPool pool(10);\n    pool.scheduleBulk(1, [&result](size_t i) {\n      return [i, &result]() { result.store(static_cast<int>(i) + 42); };\n    });\n  }\n  EXPECT_EQ(result.load(), 42);\n}\n\nTEST(ThreadPool, ScheduleBulkTwo) {\n  std::vector<int> outputs(2, 0);\n  {\n    dispenso::ThreadPool pool(10);\n    pool.scheduleBulk(2, [&outputs](size_t i) {\n      return [i, &outputs]() { outputs[i] = static_cast<int>(i) + 1; };\n    });\n  }\n  EXPECT_EQ(outputs[0], 1);\n  EXPECT_EQ(outputs[1], 2);\n}\n\nTEST(ThreadPool, ScheduleBulkLarge) {\n  constexpr size_t kWorkItems = 100000;\n  std::vector<size_t> outputs(kWorkItems, 0);\n  {\n    dispenso::ThreadPool pool(10);\n    pool.scheduleBulk(\n        kWorkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i * i; }; });\n  }\n\n  for (size_t i = 0; i < kWorkItems; ++i) {\n    EXPECT_EQ(outputs[i], i * i);\n  }\n}\n\nTEST(ThreadPool, ScheduleBulkMixedWithSchedule) {\n  static constexpr size_t kBulkItems = 500;\n  static constexpr size_t kScheduleItems = 500;\n  static constexpr size_t kTotal = kBulkItems + kScheduleItems + kBulkItems;\n  std::vector<size_t> outputs(kTotal, 0);\n  {\n    dispenso::ThreadPool pool(10);\n\n    // First bulk batch: indices [0, 500)\n    pool.scheduleBulk(\n        kBulkItems, [&outputs](size_t i) { return [i, &outputs]() { outputs[i] = i + 1; }; });\n\n    // Individual schedule: indices [500, 1000)\n    for (size_t i = kBulkItems; i < kBulkItems + kScheduleItems; ++i) {\n      pool.schedule([i, &outputs]() { outputs[i] = i + 1; });\n    }\n\n    // Second bulk batch: indices [1000, 1500)\n    pool.scheduleBulk(kBulkItems, [&outputs](size_t i) {\n      size_t idx = i + kBulkItems + kScheduleItems;\n      return [idx, &outputs]() { outputs[idx] = idx + 1; };\n    });\n  }\n\n  for (size_t i = 0; i < kTotal; ++i) {\n    EXPECT_EQ(outputs[i], i + 1);\n  }\n}\n\nTEST(ThreadPool, ScheduleBulkConcurrent) {\n  static constexpr int kTasksPerThread = 1000;\n  static constexpr int kNumSchedulers = 4;\n  std::atomic<int> counter{0};\n  {\n    dispenso::ThreadPool pool(10);\n    std::vector<std::thread> schedulers;\n    for (int t = 0; t < kNumSchedulers; ++t) {\n      schedulers.emplace_back([&pool, &counter]() {\n        pool.scheduleBulk(static_cast<size_t>(kTasksPerThread), [&counter](size_t) {\n          return [&counter]() { counter.fetch_add(1, std::memory_order_relaxed); };\n        });\n      });\n    }\n    for (auto& t : schedulers) {\n      t.join();\n    }\n  }\n  EXPECT_EQ(counter.load(), kTasksPerThread * kNumSchedulers);\n}\n\nTEST(ThreadPool, RepeatedCreationDestruction) {\n  // Verify that creating and destroying many thread pools completes promptly.\n  // This exercises the destructor's bulk-wake shutdown path and catches\n  // regressions where threads wait for epoch timeouts instead of waking\n  // immediately (particularly visible under TSAN).\n  for (int i = 0; i < 50; ++i) {\n    dispenso::ThreadPool pool(16);\n    EXPECT_EQ(pool.numThreads(), 16);\n  }\n}\n"
  },
  {
    "path": "tests/timed_task_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n#define _CRT_SECURE_NO_WARNINGS // We don't want warnings regarding the getenv use in this test.\n#endif\n\n#include <dispenso/completion_event.h>\n#include <dispenso/schedulable.h>\n#include <dispenso/task_set.h>\n#include <dispenso/timed_task.h>\n\n#include <gtest/gtest.h>\n\nusing namespace std::chrono_literals;\n\n// Some baseline error epsilon values.\nconstexpr double kp50Epsilon = 0.5e-3;\nconstexpr double kp90Epsilon = 1.0e-3;\nconstexpr double kp95Epsilon = 2.0e-3;\n\nbool g_isRealtime = false;\n\n// Adjust basic epsilons via multipliers based on real-time status and platform.\ndouble errAdjust(double eps) {\n  if (g_isRealtime) {\n#if defined(__MACH__)\n    return eps * 0.5;\n#elif defined(_WIN32)\n    return 2.0 * eps;\n#else\n    return eps * 0.33;\n#endif // platform\n  } else {\n    return eps;\n  }\n}\n\ndispenso::TimedTaskScheduler& testScheduler() {\n  static const bool rtEnv = getenv(\"TEST_WITH_REALTIME\") != nullptr;\n  if (rtEnv) {\n    static dispenso::TimedTaskScheduler sched(dispenso::ThreadPriority::kRealtime);\n    if (!g_isRealtime) {\n      std::cerr << \"Running with real-time priority\" << std::endl;\n    }\n    g_isRealtime = true;\n    return sched;\n  } else {\n    return dispenso::globalTimedTaskScheduler();\n  }\n}\n\nTEST(TimedTaskTest, RunLikelyZeroTimes) {\n  // 40 ms\n  constexpr double kWaitLen = 0.04;\n\n  double start;\n  double calledTime;\n  bool calledAtAll = false;\n\n  {\n    dispenso::ThreadPool pool(1);\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &calledAtAll]() {\n          calledTime = dispenso::getTime();\n          calledAtAll = true;\n          return true;\n        },\n        start + kWaitLen);\n  }\n\n  if (calledAtAll) {\n    EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp95Epsilon));\n    EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp95Epsilon));\n  }\n}\n\nTEST(TimedTaskTest, MoveAndRunLikelyZeroTimes) {\n  // 40 ms\n  constexpr double kWaitLen = 0.04;\n\n  double start;\n  double calledTime;\n  bool calledAtAll = false;\n\n  {\n    dispenso::ThreadPool pool(1);\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &calledAtAll]() {\n          calledTime = dispenso::getTime();\n          calledAtAll = true;\n          return true;\n        },\n        start + kWaitLen);\n\n    dispenso::TimedTask movedTo = std::move(task);\n  }\n\n  if (calledAtAll) {\n    EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp95Epsilon));\n    EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp95Epsilon));\n  }\n}\n\nTEST(TimedTaskTest, RunOnce) {\n  // 40 ms\n  constexpr double kWaitLen = 0.04;\n\n  double start;\n  double calledTime;\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &fin]() {\n          calledTime = dispenso::getTime();\n          fin.notify();\n          return true;\n        },\n        start + kWaitLen);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp95Epsilon));\n}\n\nconstexpr size_t k100Times = 100;\n\nTEST(TimedTaskTest, RunPeriodic) {\n  // 2 ms\n  constexpr double kWaitLen = 0.002;\n\n  double start;\n  std::vector<double> calledTimes(k100Times);\n  std::atomic<size_t> count(0);\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTimes, &count, &fin]() {\n          auto cur = count.fetch_add(1, std::memory_order_release);\n          calledTimes[cur] = dispenso::getTime();\n          if (cur + 1 == k100Times) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kWaitLen,\n        k100Times);\n    fin.wait();\n  }\n\n  double prev = start;\n  for (double& t : calledTimes) {\n    double absT = std::abs(kWaitLen - (t - prev));\n    prev = t;\n    t = absT;\n  }\n\n  std::sort(calledTimes.begin(), calledTimes.end());\n\n  EXPECT_LE(calledTimes[50], errAdjust(kp50Epsilon));\n  EXPECT_LE(calledTimes[90], errAdjust(kp90Epsilon));\n  EXPECT_LE(calledTimes[95], errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunPeriodicSteady) {\n  // 2 ms\n  constexpr double kWaitLen = 0.002;\n\n  double start;\n  std::vector<double> calledTimes(k100Times);\n  std::atomic<size_t> count(0);\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTimes, &count, &fin]() {\n          auto cur = count.fetch_add(1, std::memory_order_release);\n          calledTimes[cur] = dispenso::getTime();\n          if (cur + 1 == k100Times) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kWaitLen,\n        k100Times,\n        dispenso::TimedTaskType::kSteady);\n\n    fin.wait();\n  }\n\n  double prev = start;\n  for (double& t : calledTimes) {\n    double absT = std::abs(kWaitLen - (t - prev));\n    prev += kWaitLen;\n    t = absT;\n  }\n\n  std::sort(calledTimes.begin(), calledTimes.end());\n\n  EXPECT_LE(calledTimes[50], errAdjust(kp50Epsilon));\n  EXPECT_LE(calledTimes[90], errAdjust(kp90Epsilon));\n  EXPECT_LE(calledTimes[95], errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunPeriodicDontWait) {\n  // 2 ms\n  constexpr double kWaitLen = 0.002;\n\n  double start;\n  std::vector<double> calledTimes(2 * k100Times);\n  std::atomic<size_t> count(0);\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTimes, &count, &fin]() {\n          auto cur = count.fetch_add(1, std::memory_order_release);\n          calledTimes[cur] = dispenso::getTime();\n          if (cur + 1 == k100Times) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kWaitLen,\n        calledTimes.size());\n    fin.wait();\n  }\n\n  EXPECT_GE(count.load(std::memory_order_acquire), k100Times);\n\n  calledTimes.resize(k100Times);\n\n  double prev = start;\n  for (double& t : calledTimes) {\n    double absT = std::abs(kWaitLen - (t - prev));\n    prev = t;\n    t = absT;\n  }\n\n  std::sort(calledTimes.begin(), calledTimes.end());\n\n  EXPECT_LE(calledTimes[50], errAdjust(kp50Epsilon));\n  EXPECT_LE(calledTimes[90], errAdjust(kp90Epsilon));\n  EXPECT_LE(calledTimes[95], errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunPeriodicSteadyUnderLoad) {\n  // 2 ms\n  constexpr double kWaitLen = 0.002;\n\n  double start;\n  std::vector<double> calledTimes(k100Times);\n  std::atomic<size_t> count(0);\n  std::atomic<size_t> dummy(0);\n\n  dispenso::ThreadPool& pool = dispenso::globalThreadPool();\n  dispenso::ConcurrentTaskSet tasks(pool);\n  dispenso::CompletionEvent fin;\n\n  tasks.schedule([&tasks, &count, times = k100Times, &dummy]() {\n    while (count.load(std::memory_order_acquire) < times) {\n      tasks.schedule([&dummy]() { dummy.fetch_add(1, std::memory_order_relaxed); });\n    }\n  });\n\n  {\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTimes, &count, &fin]() {\n          auto cur = count.fetch_add(1, std::memory_order_acq_rel);\n          calledTimes[cur] = dispenso::getTime();\n          if (cur + 1 == k100Times) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kWaitLen,\n        k100Times,\n        dispenso::TimedTaskType::kSteady);\n    fin.wait();\n  }\n\n  tasks.wait();\n\n  double prev = start;\n  for (double& t : calledTimes) {\n    double absT = std::abs(kWaitLen - (t - prev));\n    prev += kWaitLen;\n    t = absT;\n  }\n\n  std::sort(calledTimes.begin(), calledTimes.end());\n\n#if !DISPENSO_HAS_TSAN\n  double kMultiplier = g_isRealtime ? 1.0 : 5.0;\n#else\n  double kMultiplier = 15.0;\n#endif // TSAN\n\n  EXPECT_LE(calledTimes[50], kMultiplier * errAdjust(kp50Epsilon));\n  EXPECT_LE(calledTimes[90], kMultiplier * errAdjust(kp90Epsilon));\n  EXPECT_LE(calledTimes[95], kMultiplier * errAdjust(kp95Epsilon));\n}\n\nconstexpr size_t k10Times = 10;\n\nTEST(TimedTaskTest, RunDetach) {\n  // 2 ms\n  constexpr double kWaitLen = 0.007;\n\n  double start;\n  std::vector<double> calledTimes(k10Times);\n  std::atomic<size_t> count(0);\n  dispenso::CompletionEvent fin;\n\n  {\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        dispenso::globalThreadPool(),\n        [&calledTimes, &count, &fin]() {\n          auto cur = count.fetch_add(1, std::memory_order_release);\n          calledTimes[cur] = dispenso::getTime();\n          if (cur + 1 == k10Times) {\n            fin.notify();\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kWaitLen,\n        k10Times);\n    task.detach();\n  }\n\n  fin.wait();\n\n  double prev = start;\n  for (double& t : calledTimes) {\n    double absT = std::abs(kWaitLen - (t - prev));\n    prev = t;\n    t = absT;\n  }\n\n  std::sort(calledTimes.begin(), calledTimes.end());\n\n  EXPECT_LE(calledTimes[5], errAdjust(kp50Epsilon));\n  EXPECT_LE(calledTimes[9], errAdjust(kp90Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayByDuration) {\n  // 40 ms\n  constexpr auto kWaitLenChrono = 40ms;\n  constexpr double kWaitLen = 0.04;\n\n  double start;\n  double calledTime;\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &fin]() {\n          calledTime = dispenso::getTime();\n          fin.notify();\n          return true;\n        },\n        kWaitLenChrono);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayToTimePoint) {\n  // 40 ms\n  constexpr auto kWaitLenChrono = 40ms;\n  constexpr double kWaitLen = 0.04;\n\n  double start;\n  double calledTime;\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &fin]() {\n          calledTime = dispenso::getTime();\n          fin.notify();\n          return true;\n        },\n        std::chrono::high_resolution_clock::now() + kWaitLenChrono);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayByDurationWithPeriod) {\n  constexpr auto kWaitLenChrono = 6ms;\n  constexpr double kWaitLen = 0.006;\n  constexpr auto kPeriodChrono = 2ms;\n  constexpr auto kPeriod = 0.002;\n\n  double start;\n  double calledTime[2];\n  std::atomic<int> slot(0);\n\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &slot, &fin]() {\n          auto cur = slot.fetch_add(1, std::memory_order_acq_rel);\n          calledTime[cur] = dispenso::getTime();\n          if (cur + 1 == 2) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        kWaitLenChrono,\n        kPeriodChrono,\n        2);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime[0] - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[0] - start, kWaitLen + errAdjust(kp95Epsilon));\n\n  EXPECT_GT(calledTime[1] - calledTime[0], kPeriod - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[1] - calledTime[0], kPeriod + errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayByDurationWithPeriodSteady) {\n  constexpr auto kWaitLenChrono = 6ms;\n  constexpr double kWaitLen = 0.006;\n  constexpr auto kPeriodChrono = 2ms;\n  constexpr auto kPeriod = 0.002;\n\n  double start;\n  double calledTime[2];\n  std::atomic<int> slot(0);\n\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &slot, &fin]() {\n          auto cur = slot.fetch_add(1, std::memory_order_acq_rel);\n          calledTime[cur] = dispenso::getTime();\n          if (cur + 1 == 2) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        kWaitLenChrono,\n        kPeriodChrono,\n        2);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime[0] - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[0] - start, kWaitLen + errAdjust(kp95Epsilon));\n\n  EXPECT_GT(calledTime[1] - start, (kWaitLen + kPeriod) - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[1] - start, (kWaitLen + kPeriod) + errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayToTimepointWithPeriod) {\n  constexpr auto kWaitLenChrono = 6ms;\n  constexpr double kWaitLen = 0.006;\n  constexpr auto kPeriodChrono = 2ms;\n  constexpr auto kPeriod = 0.002;\n\n  double start;\n  double calledTime[2];\n  std::atomic<int> slot(0);\n\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &slot, &fin]() {\n          auto cur = slot.fetch_add(1, std::memory_order_acq_rel);\n          calledTime[cur] = dispenso::getTime();\n          if (cur + 1 == 2) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        std::chrono::high_resolution_clock::now() + kWaitLenChrono,\n        kPeriodChrono,\n        2);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime[0] - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[0] - start, kWaitLen + errAdjust(kp95Epsilon));\n\n  EXPECT_GT(calledTime[1] - calledTime[0], kPeriod - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[1] - calledTime[0], kPeriod + errAdjust(kp95Epsilon));\n}\n\nTEST(TimedTaskTest, RunChronoDelayToTimepointWithPeriodSteady) {\n  constexpr auto kWaitLenChrono = 6ms;\n  constexpr double kWaitLen = 0.006;\n  constexpr auto kPeriodChrono = 2ms;\n  constexpr auto kPeriod = 0.002;\n\n  double start;\n  double calledTime[2];\n  std::atomic<int> slot(0);\n\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &slot, &fin]() {\n          auto cur = slot.fetch_add(1, std::memory_order_acq_rel);\n          calledTime[cur] = dispenso::getTime();\n          if (cur + 1 == 2) {\n            fin.notify();\n            return false;\n          }\n          return true;\n        },\n        std::chrono::high_resolution_clock::now() + kWaitLenChrono,\n        kPeriodChrono,\n        2);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime[0] - start, kWaitLen - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[0] - start, kWaitLen + errAdjust(kp95Epsilon));\n\n  EXPECT_GT(calledTime[1] - start, (kWaitLen + kPeriod) - errAdjust(kp95Epsilon));\n  EXPECT_LT(calledTime[1] - start, (kWaitLen + kPeriod) + errAdjust(kp95Epsilon));\n}\n\nconstexpr size_t kRunForever = std::numeric_limits<size_t>::max();\n\nTEST(TimedTaskTest, RunOnceImmediatelyLongPeriod) {\n  constexpr double kWaitLen = 0.0;\n  constexpr double kPeriod = 100.0;\n\n  double start;\n  double calledTime;\n  dispenso::CompletionEvent fin;\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&calledTime, &fin]() {\n          calledTime = dispenso::getTime();\n          fin.notify();\n          return true;\n        },\n        start + kWaitLen,\n        kPeriod,\n        kRunForever);\n\n    fin.wait();\n  }\n\n  EXPECT_GT(calledTime - start, kWaitLen - errAdjust(kp50Epsilon));\n  EXPECT_LT(calledTime - start, kWaitLen + errAdjust(kp50Epsilon));\n}\n\nconstexpr int kTerminateCount = 7;\n\nTEST(TimedTaskTest, CancelViaProvidedFunction) {\n  constexpr double kWaitLen = 0.004;\n  // Make the period very tiny\n  constexpr double kPeriod = 50e-6;\n\n  double start;\n  std::atomic<int> counter(0);\n\n  {\n    dispenso::ImmediateInvoker pool;\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        pool,\n        [&counter]() {\n          if (counter.fetch_add(1, std::memory_order_acq_rel) + 1 == kTerminateCount) {\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kPeriod,\n        kRunForever);\n\n    while (counter.load(std::memory_order_acquire) != kTerminateCount) {\n    }\n\n    // Task should be terminating\n    std::this_thread::sleep_for(10ms);\n  }\n\n  EXPECT_EQ(counter.load(std::memory_order_acquire), kTerminateCount);\n}\n\nTEST(TimedTaskTest, CancelViaProvidedFunctionInThreadPool) {\n  constexpr double kWaitLen = 0.004;\n  // Make the period very tiny\n  constexpr double kPeriod = 50e-6;\n\n  double start;\n  std::atomic<int> counter(0);\n\n  {\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        dispenso::globalThreadPool(),\n        [&counter]() {\n          if (counter.fetch_add(1, std::memory_order_acq_rel) + 1 == kTerminateCount) {\n            return false;\n          }\n          return true;\n        },\n        start + kWaitLen,\n        kPeriod,\n        kRunForever);\n\n    while (counter.load(std::memory_order_acquire) != kTerminateCount) {\n    }\n\n    // Task should be terminating\n    std::this_thread::sleep_for(10ms);\n  }\n\n  EXPECT_GE(counter.load(std::memory_order_acquire), kTerminateCount);\n  EXPECT_LE(counter.load(std::memory_order_acquire), kTerminateCount + 1);\n}\n\nTEST(TimedTaskTest, FunctionDestructionPostTaskDestruct) {\n  constexpr double kWaitLen = 0.004;\n  // Make the period very tiny\n  constexpr double kPeriod = 50e-6;\n\n  double start;\n\n  {\n    std::vector<size_t> dummyObj1;\n\n    struct Dummy {\n      std::vector<size_t>& vec;\n\n      ~Dummy() {\n        if (vec.size() != 0) {\n          std::cerr << \"INVALID CALL TO DESTRUCTOR\" << std::endl;\n          std::abort();\n        }\n      }\n\n    } dummy{dummyObj1};\n\n    start = dispenso::getTime();\n    dispenso::TimedTask task = testScheduler().schedule(\n        dispenso::globalThreadPool(),\n        [dummy]() { return true; },\n        start + kWaitLen,\n        kPeriod,\n        kRunForever);\n    // Here task goes out of scope\n  }\n\n  // Goal: passed function destructor should never execute out here... if it does it will\n  // incorrectly reference value that went out of scope\n}\n"
  },
  {
    "path": "tests/timing_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/timing.h>\n\n#include <chrono>\n#include <cmath>\n#include <thread>\n\n#include <gtest/gtest.h>\n\n// These tests are disabled under TSAN because timing-based tests are inherently\n// sensitive to instrumentation overhead and thread scheduling, making them flaky\n// in sanitizer builds.\n\n#if !DISPENSO_HAS_TSAN\n\nTEST(Timing, GetTimeReturnsNonNegative) {\n  double t = dispenso::getTime();\n  EXPECT_GE(t, 0.0);\n}\n\nTEST(Timing, GetTimeIsMonotonic) {\n  double prev = dispenso::getTime();\n  for (int i = 0; i < 100; ++i) {\n    double cur = dispenso::getTime();\n    EXPECT_GE(cur, prev);\n    prev = cur;\n  }\n}\n\nTEST(Timing, GetTimeProgresses) {\n  double start = dispenso::getTime();\n  std::this_thread::sleep_for(std::chrono::milliseconds(10));\n  double end = dispenso::getTime();\n\n  // After sleeping 10ms, time should have advanced by at least 5ms\n  // (allowing for timing imprecision)\n  EXPECT_GT(end - start, 0.005);\n}\n\nTEST(Timing, StatisticalAccuracy) {\n  // Run many iterations and verify that most measurements are within tolerance\n  // of std::chrono. This is a statistical test that allows for some outliers\n  // due to OS scheduling, context switches, etc.\n\n  constexpr int kIterations = 1000;\n  constexpr int kMinSuccesses = 900; // 90% must pass\n  constexpr double kToleranceSeconds = 2e-6; // 2 microseconds tolerance\n\n  int successes = 0;\n\n  for (int i = 0; i < kIterations; ++i) {\n    auto chronoStart = std::chrono::high_resolution_clock::now();\n    double dispensoStart = dispenso::getTime();\n\n    // Small busy-wait to accumulate some time\n    volatile int dummy = 0;\n    for (int j = 0; j < 1000; ++j) {\n      dummy += j;\n    }\n    (void)dummy;\n\n    auto chronoEnd = std::chrono::high_resolution_clock::now();\n    double dispensoEnd = dispenso::getTime();\n\n    double chronoElapsed = std::chrono::duration<double>(chronoEnd - chronoStart).count();\n    double dispensoElapsed = dispensoEnd - dispensoStart;\n\n    // Check if the measurements are within tolerance\n    double diff = std::abs(chronoElapsed - dispensoElapsed);\n    if (diff < kToleranceSeconds) {\n      ++successes;\n    }\n  }\n\n  EXPECT_GE(successes, kMinSuccesses)\n      << \"Expected at least \" << kMinSuccesses << \" out of \" << kIterations\n      << \" timing measurements to be within \" << (kToleranceSeconds * 1e6)\n      << \"us tolerance, but only \" << successes << \" were.\";\n}\n\nTEST(Timing, LongerDurationAccuracy) {\n  // Test accuracy over a longer duration by comparing dispenso timing to chrono\n  // We use sleep to introduce a delay, but measure with both timing systems\n  constexpr int kIterations = 10;\n  constexpr double kSleepSeconds = 0.02; // 20ms minimum sleep\n  constexpr double kToleranceRatio = 0.10; // 10% tolerance between timing systems\n\n  for (int i = 0; i < kIterations; ++i) {\n    auto chronoStart = std::chrono::steady_clock::now();\n    double dispensoStart = dispenso::getTime();\n\n    std::this_thread::sleep_for(\n        std::chrono::microseconds(static_cast<int64_t>(kSleepSeconds * 1e6)));\n\n    double dispensoEnd = dispenso::getTime();\n    auto chronoEnd = std::chrono::steady_clock::now();\n\n    double dispensoElapsed = dispensoEnd - dispensoStart;\n    double chronoElapsed = std::chrono::duration<double>(chronoEnd - chronoStart).count();\n\n    // Both should report at least the sleep duration (sleep is a minimum wait)\n    EXPECT_GE(dispensoElapsed, kSleepSeconds * 0.9)\n        << \"Iteration \" << i << \": dispenso elapsed time \" << dispensoElapsed\n        << \" is too short compared to sleep duration \" << kSleepSeconds;\n\n    // dispenso and chrono should agree within tolerance\n    double diff = std::abs(chronoElapsed - dispensoElapsed);\n    double maxDiff = chronoElapsed * kToleranceRatio;\n    EXPECT_LE(diff, maxDiff) << \"Iteration \" << i << \": dispenso (\" << dispensoElapsed\n                             << \"s) and chrono (\" << chronoElapsed << \"s) differ by \" << diff\n                             << \"s, which exceeds \" << (kToleranceRatio * 100) << \"% tolerance\";\n  }\n}\n\nTEST(Timing, RapidCalls) {\n  // Verify that rapid successive calls don't produce anomalies\n  constexpr int kIterations = 10000;\n  double times[kIterations];\n\n  for (int i = 0; i < kIterations; ++i) {\n    times[i] = dispenso::getTime();\n  }\n\n  // All times should be monotonically non-decreasing\n  for (int i = 1; i < kIterations; ++i) {\n    EXPECT_GE(times[i], times[i - 1]) << \"Time went backwards at index \" << i;\n  }\n\n  // Total elapsed time should be small (< 1 second for 10k calls)\n  double totalElapsed = times[kIterations - 1] - times[0];\n  EXPECT_LT(totalElapsed, 1.0) << \"10000 getTime() calls took \" << totalElapsed << \" seconds\";\n}\n\n#endif // !DISPENSO_HAS_TSAN\n"
  },
  {
    "path": "tests/util_test.cpp",
    "content": "/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n#include <dispenso/util.h>\n\n#include <dispenso/platform.h>\n\n#include <atomic>\n#include <cstdint>\n#include <memory>\n#include <thread>\n#include <vector>\n\n#include <gtest/gtest.h>\n\nusing dispenso::ssize_t;\n\n// Global test helpers for reference counting tests\nint RefCountedCount = 0;\nstruct RefCounted {\n  RefCounted() {\n    ++RefCountedCount;\n  }\n  ~RefCounted() {\n    --RefCountedCount;\n  }\n};\n\nint NonTrivialConstructCount = 0;\nint NonTrivialDestructCount = 0;\nstruct NonTrivial {\n  int value;\n\n  NonTrivial(int v) : value(v) {\n    ++NonTrivialConstructCount;\n  }\n\n  NonTrivial(const NonTrivial& other) : value(other.value) {\n    ++NonTrivialConstructCount;\n  }\n\n  NonTrivial(NonTrivial&& other) : value(other.value) {\n    other.value = -1;\n    ++NonTrivialConstructCount;\n  }\n\n  ~NonTrivial() {\n    ++NonTrivialDestructCount;\n  }\n};\n\nTEST(Util, AlignedMallocAndFree) {\n  // Test basic allocation and deallocation\n  void* ptr = dispenso::alignedMalloc(1024, 64);\n  ASSERT_NE(ptr, nullptr);\n  EXPECT_EQ(reinterpret_cast<uintptr_t>(ptr) % 64, 0u) << \"Pointer should be 64-byte aligned\";\n  dispenso::alignedFree(ptr);\n\n  // Test cache-line aligned version\n  ptr = dispenso::alignedMalloc(256);\n  ASSERT_NE(ptr, nullptr);\n  EXPECT_EQ(reinterpret_cast<uintptr_t>(ptr) % dispenso::kCacheLineSize, 0u)\n      << \"Pointer should be cache-line aligned\";\n  dispenso::alignedFree(ptr);\n\n  // Test nullptr is safe to free\n  dispenso::alignedFree(nullptr);\n\n  // Test various alignments\n  for (size_t alignment : {8, 16, 32, 64, 128, 256}) {\n    ptr = dispenso::alignedMalloc(100, alignment);\n    ASSERT_NE(ptr, nullptr);\n    EXPECT_EQ(reinterpret_cast<uintptr_t>(ptr) % alignment, 0u)\n        << \"Pointer should be aligned to \" << alignment;\n    dispenso::alignedFree(ptr);\n  }\n}\n\nTEST(Util, AlignedMallocUsable) {\n  // Verify allocated memory is actually usable\n  constexpr size_t kSize = 1024;\n  uint8_t* ptr = static_cast<uint8_t*>(dispenso::alignedMalloc(kSize, 64));\n  ASSERT_NE(ptr, nullptr);\n\n  // Write pattern to memory\n  for (size_t i = 0; i < kSize; ++i) {\n    ptr[i] = static_cast<uint8_t>(i & 0xFF);\n  }\n\n  // Verify pattern\n  for (size_t i = 0; i < kSize; ++i) {\n    EXPECT_EQ(ptr[i], static_cast<uint8_t>(i & 0xFF));\n  }\n\n  dispenso::alignedFree(ptr);\n}\n\nTEST(Util, AlignedDeleter) {\n  // Test with unique_ptr\n  {\n    struct TestStruct {\n      int value;\n      ~TestStruct() {\n        value = -1;\n      }\n    };\n\n    void* mem = dispenso::alignedMalloc(sizeof(TestStruct), 64);\n    ASSERT_NE(mem, nullptr);\n\n    std::unique_ptr<TestStruct, dispenso::AlignedDeleter<TestStruct>> ptr(new (mem) TestStruct{42});\n    EXPECT_EQ(ptr->value, 42);\n  }\n  // Deleter should have freed memory and called destructor\n\n  // Test with shared_ptr - use global RefCounted\n  RefCountedCount = 0;\n\n  {\n    void* mem = dispenso::alignedMalloc(sizeof(RefCounted), 64);\n    std::shared_ptr<RefCounted> ptr1(\n        new (mem) RefCounted(), dispenso::AlignedDeleter<RefCounted>());\n    EXPECT_EQ(RefCountedCount, 1);\n\n    std::shared_ptr<RefCounted> ptr2 = ptr1;\n    EXPECT_EQ(RefCountedCount, 1);\n  }\n\n  EXPECT_EQ(RefCountedCount, 0);\n}\n\nTEST(Util, AlignToCacheLine) {\n  // alignToCacheLine rounds up to next cache line boundary\n  constexpr auto kCLS = dispenso::kCacheLineSize;\n  // For 0, it stays 0 (already aligned)\n  EXPECT_EQ(dispenso::alignToCacheLine(0), 0u);\n  EXPECT_EQ(dispenso::alignToCacheLine(1), kCLS);\n  EXPECT_EQ(dispenso::alignToCacheLine(kCLS - 1), kCLS);\n  EXPECT_EQ(dispenso::alignToCacheLine(kCLS), kCLS);\n  EXPECT_EQ(dispenso::alignToCacheLine(kCLS + 1), kCLS * 2);\n  EXPECT_EQ(dispenso::alignToCacheLine(kCLS * 2), kCLS * 2);\n  EXPECT_EQ(dispenso::alignToCacheLine(kCLS * 2 + 1), kCLS * 3);\n}\n\nTEST(Util, CpuRelax) {\n  // Just verify it doesn't crash\n  for (int i = 0; i < 10; ++i) {\n    dispenso::cpuRelax();\n  }\n}\n\nTEST(Util, NextPow2) {\n  // Compile-time tests\n  static_assert(dispenso::nextPow2(0) == 0, \"nextPow2(0) should be 0\");\n  static_assert(dispenso::nextPow2(1) == 1, \"nextPow2(1) should be 1\");\n  static_assert(dispenso::nextPow2(2) == 2, \"nextPow2(2) should be 2\");\n  static_assert(dispenso::nextPow2(3) == 4, \"nextPow2(3) should be 4\");\n  static_assert(dispenso::nextPow2(4) == 4, \"nextPow2(4) should be 4\");\n  static_assert(dispenso::nextPow2(5) == 8, \"nextPow2(5) should be 8\");\n  static_assert(dispenso::nextPow2(17) == 32, \"nextPow2(17) should be 32\");\n  static_assert(dispenso::nextPow2(64) == 64, \"nextPow2(64) should be 64\");\n  static_assert(dispenso::nextPow2(65) == 128, \"nextPow2(65) should be 128\");\n  static_assert(dispenso::nextPow2(1000) == 1024, \"nextPow2(1000) should be 1024\");\n\n  // Runtime tests\n  EXPECT_EQ(dispenso::nextPow2(0), 0);\n  EXPECT_EQ(dispenso::nextPow2(1), 1);\n  EXPECT_EQ(dispenso::nextPow2(3), 4);\n  EXPECT_EQ(dispenso::nextPow2(17), 32);\n  EXPECT_EQ(dispenso::nextPow2(1ULL << 30), 1ULL << 30);\n  EXPECT_EQ(dispenso::nextPow2((1ULL << 30) + 1), 1ULL << 31);\n}\n\nTEST(Util, Log2Const) {\n  // Compile-time tests\n  static_assert(dispenso::log2const(1) == 0, \"log2(1) should be 0\");\n  static_assert(dispenso::log2const(2) == 1, \"log2(2) should be 1\");\n  static_assert(dispenso::log2const(4) == 2, \"log2(4) should be 2\");\n  static_assert(dispenso::log2const(8) == 3, \"log2(8) should be 3\");\n  static_assert(dispenso::log2const(16) == 4, \"log2(16) should be 4\");\n  static_assert(dispenso::log2const(64) == 6, \"log2(64) should be 6\");\n  static_assert(dispenso::log2const(100) == 6, \"log2(100) should be 6\");\n  static_assert(dispenso::log2const(127) == 6, \"log2(127) should be 6\");\n  static_assert(dispenso::log2const(128) == 7, \"log2(128) should be 7\");\n\n  // Runtime tests\n  EXPECT_EQ(dispenso::log2const(1), 0u);\n  EXPECT_EQ(dispenso::log2const(2), 1u);\n  EXPECT_EQ(dispenso::log2const(64), 6u);\n  EXPECT_EQ(dispenso::log2const(1024), 10u);\n  EXPECT_EQ(dispenso::log2const(1ULL << 32), 32u);\n  EXPECT_EQ(dispenso::log2const(1ULL << 63), 63u);\n}\n\nTEST(Util, Log2) {\n  // Runtime log2 should match constexpr version\n  EXPECT_EQ(dispenso::log2(1), dispenso::log2const(1));\n  EXPECT_EQ(dispenso::log2(2), dispenso::log2const(2));\n  EXPECT_EQ(dispenso::log2(64), dispenso::log2const(64));\n  EXPECT_EQ(dispenso::log2(100), dispenso::log2const(100));\n  EXPECT_EQ(dispenso::log2(1024), dispenso::log2const(1024));\n  EXPECT_EQ(dispenso::log2(1ULL << 32), dispenso::log2const(1ULL << 32));\n\n  // Test powers of 2\n  for (uint32_t i = 0; i < 64; ++i) {\n    uint64_t val = 1ULL << i;\n    EXPECT_EQ(dispenso::log2(val), i);\n  }\n\n  // Test non-powers of 2 (floor behavior)\n  EXPECT_EQ(dispenso::log2(3), 1u);\n  EXPECT_EQ(dispenso::log2(5), 2u);\n  EXPECT_EQ(dispenso::log2(127), 6u);\n  EXPECT_EQ(dispenso::log2(129), 7u);\n}\n\nTEST(Util, AlignedBuffer) {\n  struct TestType {\n    alignas(32) char data[64];\n  };\n\n  dispenso::AlignedBuffer<TestType> buf;\n  // The struct containing the buffer has proper alignment, not the char array itself\n  EXPECT_GE(alignof(decltype(buf)), alignof(TestType));\n  EXPECT_GE(sizeof(buf.b), sizeof(TestType));\n\n  // Verify we can construct in the buffer\n  TestType* obj = new (buf.b) TestType();\n  obj->data[0] = 42;\n  EXPECT_EQ(obj->data[0], 42);\n  obj->~TestType();\n}\n\nTEST(Util, AlignedAtomic) {\n  dispenso::AlignedAtomic<int> atomic;\n\n  // Verify alignment\n  EXPECT_EQ(reinterpret_cast<uintptr_t>(&atomic) % dispenso::kCacheLineSize, 0u);\n\n  // Verify it works as atomic\n  int val = 42;\n  atomic.store(&val);\n  EXPECT_EQ(atomic.load(), &val);\n\n  // Test from multiple threads to verify atomicity\n  std::atomic<bool> ready{false};\n  std::atomic<bool> done{false};\n\n  std::thread t([&]() {\n    while (!ready.load(std::memory_order_acquire)) {\n      dispenso::cpuRelax();\n    }\n    int* expected = nullptr;\n    atomic.compare_exchange_strong(expected, &val);\n    done.store(true, std::memory_order_release);\n  });\n\n  int* ptr = nullptr;\n  atomic.store(ptr);\n  ready.store(true, std::memory_order_release);\n\n  while (!done.load(std::memory_order_acquire)) {\n    dispenso::cpuRelax();\n  }\n\n  EXPECT_EQ(atomic.load(), &val);\n  t.join();\n}\n\nTEST(Util, OpResult) {\n  // Test default construction\n  dispenso::OpResult<int> r1;\n  EXPECT_FALSE(r1);\n  EXPECT_FALSE(r1.has_value());\n\n  // Test value construction\n  dispenso::OpResult<int> r2(42);\n  EXPECT_TRUE(r2);\n  EXPECT_TRUE(r2.has_value());\n  EXPECT_EQ(r2.value(), 42);\n\n  // Test copy construction\n  dispenso::OpResult<int> r3(r2);\n  EXPECT_TRUE(r3);\n  EXPECT_EQ(r3.value(), 42);\n\n  // Test move construction\n  dispenso::OpResult<int> r4(std::move(r3));\n  EXPECT_TRUE(r4);\n  EXPECT_EQ(r4.value(), 42);\n  EXPECT_FALSE(r3); // Moved-from should be empty\n\n  // Test copy assignment\n  dispenso::OpResult<int> r5;\n  r5 = r2;\n  EXPECT_TRUE(r5);\n  EXPECT_EQ(r5.value(), 42);\n\n  // Test move assignment\n  dispenso::OpResult<int> r6;\n  r6 = std::move(r5);\n  EXPECT_TRUE(r6);\n  EXPECT_EQ(r6.value(), 42);\n  EXPECT_FALSE(r5);\n\n  // Test emplace\n  dispenso::OpResult<int> r7;\n  r7.emplace(100);\n  EXPECT_TRUE(r7);\n  EXPECT_EQ(r7.value(), 100);\n\n  // Test self-assignment (suppressing warnings as this is intentional for testing)\n  // clang-format off\n  DISPENSO_DISABLE_WARNING_PUSH\n#if defined(__clang__)\n  DISPENSO_DISABLE_WARNING(-Wself-assign-overloaded)\n#endif\n#if defined(__clang__) || defined(__GNUC__)\n  DISPENSO_DISABLE_WARNING(-Wself-move)\n#endif\n  // clang-format on\n  r7 = r7;\n  EXPECT_TRUE(r7);\n  EXPECT_EQ(r7.value(), 100);\n\n  r7 = std::move(r7);\n  EXPECT_TRUE(r7);\n  EXPECT_EQ(r7.value(), 100);\n  DISPENSO_DISABLE_WARNING_POP\n}\n\nTEST(Util, OpResultWithNonTrivialType) {\n  NonTrivialConstructCount = 0;\n  NonTrivialDestructCount = 0;\n\n  {\n    dispenso::OpResult<NonTrivial> r1(NonTrivial(42));\n    EXPECT_EQ(r1.value().value, 42);\n    EXPECT_GT(NonTrivialConstructCount, 0);\n\n    dispenso::OpResult<NonTrivial> r2(r1);\n    EXPECT_EQ(r2.value().value, 42);\n\n    r1.emplace(100);\n    EXPECT_EQ(r1.value().value, 100);\n  }\n\n  // All objects should be destroyed\n  EXPECT_EQ(NonTrivialConstructCount, NonTrivialDestructCount);\n}\n\nTEST(Util, StaticChunkSize) {\n  // Test exact division\n  auto chunking = dispenso::staticChunkSize(100, 10);\n  EXPECT_EQ(chunking.ceilChunkSize, 10);\n  EXPECT_EQ(chunking.transitionTaskIndex, 10);\n\n  // Verify all items are accounted for\n  ssize_t total = 0;\n  for (ssize_t i = 0; i < 10; ++i) {\n    ssize_t chunkSize =\n        (i < chunking.transitionTaskIndex) ? chunking.ceilChunkSize : chunking.ceilChunkSize - 1;\n    total += chunkSize;\n  }\n  EXPECT_EQ(total, 100);\n\n  // Test with remainder\n  chunking = dispenso::staticChunkSize(100, 8);\n  EXPECT_EQ(chunking.ceilChunkSize, 13);\n  EXPECT_EQ(chunking.transitionTaskIndex, 4);\n\n  // Verify: 4 chunks of 13, 4 chunks of 12\n  total = 0;\n  for (ssize_t i = 0; i < 8; ++i) {\n    ssize_t chunkSize =\n        (i < chunking.transitionTaskIndex) ? chunking.ceilChunkSize : chunking.ceilChunkSize - 1;\n    total += chunkSize;\n  }\n  EXPECT_EQ(total, 100);\n\n  // Test edge cases\n  chunking = dispenso::staticChunkSize(1, 10);\n  EXPECT_EQ(chunking.ceilChunkSize, 1);\n  EXPECT_EQ(chunking.transitionTaskIndex, 1);\n\n  chunking = dispenso::staticChunkSize(7, 3);\n  EXPECT_EQ(chunking.ceilChunkSize, 3);\n  EXPECT_EQ(chunking.transitionTaskIndex, 1);\n  // 1 chunk of 3, 2 chunks of 2 = 3 + 2 + 2 = 7\n  total = 0;\n  for (ssize_t i = 0; i < 3; ++i) {\n    ssize_t chunkSize =\n        (i < chunking.transitionTaskIndex) ? chunking.ceilChunkSize : chunking.ceilChunkSize - 1;\n    total += chunkSize;\n  }\n  EXPECT_EQ(total, 7);\n}\n\nTEST(Util, StaticChunkSizeLoadBalancing) {\n  // Verify load balancing is good\n  // Maximum difference between chunks should be 1\n  for (ssize_t items : {100, 101, 127, 256, 1000, 10001}) {\n    for (ssize_t chunks : {2, 4, 7, 8, 16, 32}) {\n      auto chunking = dispenso::staticChunkSize(items, chunks);\n\n      ssize_t minChunk = chunking.ceilChunkSize - 1;\n      ssize_t maxChunk = chunking.ceilChunkSize;\n\n      EXPECT_LE(maxChunk - minChunk, 1)\n          << \"Chunk sizes should differ by at most 1 for items=\" << items << \" chunks=\" << chunks;\n\n      // Verify total\n      ssize_t total = 0;\n      for (ssize_t i = 0; i < chunks; ++i) {\n        ssize_t chunkSize = (i < chunking.transitionTaskIndex) ? chunking.ceilChunkSize\n                                                               : chunking.ceilChunkSize - 1;\n        total += chunkSize;\n      }\n      EXPECT_EQ(total, items) << \"Total items mismatch for items=\" << items << \" chunks=\" << chunks;\n    }\n  }\n}\n"
  }
]